スレッドのいくつかの概念
スレッドは、オペレーティングシステムが演算スケジューリングできる最小単位であり、プロセスに含まれる.典型的なUNIX/Linuxプロセスは、1つの制御スレッドのみと見なすことができる.
スレッドには、プロセス内の実行環境を示すために必要な情報が含まれます.これには、プロセス内でスレッドを識別するスレッドID、レジスタ値のセット、スタック、スケジューリング優先度およびポリシー、信号シールドワード、errno変数、およびスレッドプライベートデータ(独立したスタック、共有スタックがない)が含まれます.プロセス内のすべての情報は、実行可能なプログラムテキスト、プログラムのグローバルメモリおよびスタックメモリ、スタック、およびファイル記述子を含むプロセス内のスレッドに対して共有されます.
スレッドID
プロセスIDのように、スレッドごとに1つのスレッドIDがあります.プロセスIDはシステム全体で一意ですが、スレッドIDはその属するプロセス内でのみ有効です.スレッドIDはpthread_tデータ型は、実装時にpthread_を1つのデータ構造で表すことができることを示す.tデータ型のため,移植可能なオペレーティングシステムでは整数として処理できない.したがって2つのスレッドIDを比較するには、関数でなければなりません
#include
int pthread_equal(pthread_t tid1, pthread_t tid2);
自分のIDを取得するには
#incude
pthread_t pthread_self(void);
スレッドの作成
スレッドを作成する前に、プロセスにはマスタースレッドが1つしかないと考えられます.スレッドを作成して使用
#include
int pthread_create(pthread_t *restrict tidp,
const pthread_attr_t *restrict attr.
void *(*start_rtn)(void *), void *restrict arg);
スレッドの作成に成功して返されると、tidpが指すメモリユニットは、新しく作成されたスレッドのスレッドIDに設定される.attrパラメータは、さまざまなスレッドプロパティをカスタマイズするために使用されます.
新しく作成したスレッドはstart_からrtn関数アドレスは実行を開始し、この関数の後にタイプのないポインタパラメータargがあり、複数のパラメータを入力する場合は、複数のパラメータを構造体にし、構造体に入力します.
スレッドが作成された後、どのスレッドが先に実行されるかは保証されません.新しく作成されたか、スレッドが呼び出されたかです.新しく作成されたスレッドは、プロセスのアドレス空間にアクセスし、呼び出しスレッドの浮動小数点環境と信号シールドワードを継承することができるが、このスレッドの未決信号セットは消去される.
pthreadが失敗するとエラーコードが返され、他のPOSIX関数のようにerrnoが設定されません.各スレッドはerrnoのコピーを提供します.これはerrnoを使用する既存の関数と互換性を持つためだけです.
次のコードでテストできます.機能はプリントスレッドIDです.
Fedoraでの実行結果は次のとおりです.
main thread: pid 3922 tid 3078109440 (0xb7783900) new thread: pid 3922 tid 3078105920 (0xb7782b40)
sleep(1)の目的は,プライマリスレッドの終了を防止することである.pthread_経由selfはpthread_でスレッドIDを取得するcreateが戻る前に、関数が実行されている可能性があります.
スレッド終了
プロセス内の任意のスレッドがexitを呼び出し、exit,_Exitプロセス全体が終了します.信号のデフォルト動作が終了プロセスである場合、スレッドに送信してもプロセスは終了します.
個々のスレッドを終了するには、次の方法を使用します.
1、スレッドは起動ルーチンからのみ返され、戻り値はスレッド終了コードである.
2、スレッドは同じプロセスの他のスレッドによってキャンセルされます.
3、pthread_を呼び出すexit
#include
void pthread_exit(void *rval_ptr)
ここでrval_ptrはタイプレスポインタであり、起動ルーチンパラメータに渡されるのと同様である.同じプロセス内の他のプロセスはpthread_を呼び出すことができます.join関数はこのポインタを取得します.
#include
void pthread_join(pthread_t thread, void **rval_prt);
ここで注意したいのは、スレッドが終了した状態の値であり、スレッドのスタックには使用できません.スタック上でスレッドが終了すると、スタック空間が解放されます.
スレッドは、同じプロセス内の他のスレッドをキャンセルできます.
#include
int pthread_cancel(pthread_t tid)
スレッドは、プロセスのatexitのように、終了時に呼び出されたクリーンアップ関数を登録できます.プロセッサはスタックに記録されます.したがって、呼び出し順序は登録順序とは逆です.
#inlcude
void pthread_cleanup_push(void (*rtn) (void *), void *arg);
void pthread_cleanup_pop(int execute);
コードを書いて、上のいくつかの関数をテストします.
Fedoraでの実行結果は次のとおりです.
thread 2 start thread 2 push complete thread 1 start thread 1 push complete cleanup:thread 1 second handler cleanup:thread 1 first handler thread 1 exit code 1 thread 2 exit code 2
スレッドには、プロセス内の実行環境を示すために必要な情報が含まれます.これには、プロセス内でスレッドを識別するスレッドID、レジスタ値のセット、スタック、スケジューリング優先度およびポリシー、信号シールドワード、errno変数、およびスレッドプライベートデータ(独立したスタック、共有スタックがない)が含まれます.プロセス内のすべての情報は、実行可能なプログラムテキスト、プログラムのグローバルメモリおよびスタックメモリ、スタック、およびファイル記述子を含むプロセス内のスレッドに対して共有されます.
スレッドID
プロセスIDのように、スレッドごとに1つのスレッドIDがあります.プロセスIDはシステム全体で一意ですが、スレッドIDはその属するプロセス内でのみ有効です.スレッドIDはpthread_tデータ型は、実装時にpthread_を1つのデータ構造で表すことができることを示す.tデータ型のため,移植可能なオペレーティングシステムでは整数として処理できない.したがって2つのスレッドIDを比較するには、関数でなければなりません
#include
int pthread_equal(pthread_t tid1, pthread_t tid2);
自分のIDを取得するには
#incude
pthread_t pthread_self(void);
スレッドの作成
スレッドを作成する前に、プロセスにはマスタースレッドが1つしかないと考えられます.スレッドを作成して使用
#include
int pthread_create(pthread_t *restrict tidp,
const pthread_attr_t *restrict attr.
void *(*start_rtn)(void *), void *restrict arg);
スレッドの作成に成功して返されると、tidpが指すメモリユニットは、新しく作成されたスレッドのスレッドIDに設定される.attrパラメータは、さまざまなスレッドプロパティをカスタマイズするために使用されます.
新しく作成したスレッドはstart_からrtn関数アドレスは実行を開始し、この関数の後にタイプのないポインタパラメータargがあり、複数のパラメータを入力する場合は、複数のパラメータを構造体にし、構造体に入力します.
スレッドが作成された後、どのスレッドが先に実行されるかは保証されません.新しく作成されたか、スレッドが呼び出されたかです.新しく作成されたスレッドは、プロセスのアドレス空間にアクセスし、呼び出しスレッドの浮動小数点環境と信号シールドワードを継承することができるが、このスレッドの未決信号セットは消去される.
pthreadが失敗するとエラーコードが返され、他のPOSIX関数のようにerrnoが設定されません.各スレッドはerrnoのコピーを提供します.これはerrnoを使用する既存の関数と互換性を持つためだけです.
次のコードでテストできます.機能はプリントスレッドIDです.
#include<pthread.h>
pthread_t ntid;
void
printids(const char *s)
{
pid_t pid;
pthread_t tid;
pid=getpid();
tid=pthread_self();
printf("%s pid %u tid %u (0x%x)
",s,(unsigned int)pid,(unsigned int)tid,(unsigned int)tid);
}
void*
thr_fn(void *arg)
{
printids("new thread:");
return ((void*)0);
}
int main(void)
{
int err;
err=pthread_create(&ntid,NULL,thr_fn,NULL);
if(err!=0)
printf("can't create thread:%s
",strerror(err));
printids("main thread:");
sleep(1);
exit(0);
}
Fedoraでの実行結果は次のとおりです.
main thread: pid 3922 tid 3078109440 (0xb7783900) new thread: pid 3922 tid 3078105920 (0xb7782b40)
sleep(1)の目的は,プライマリスレッドの終了を防止することである.pthread_経由selfはpthread_でスレッドIDを取得するcreateが戻る前に、関数が実行されている可能性があります.
スレッド終了
プロセス内の任意のスレッドがexitを呼び出し、exit,_Exitプロセス全体が終了します.信号のデフォルト動作が終了プロセスである場合、スレッドに送信してもプロセスは終了します.
個々のスレッドを終了するには、次の方法を使用します.
1、スレッドは起動ルーチンからのみ返され、戻り値はスレッド終了コードである.
2、スレッドは同じプロセスの他のスレッドによってキャンセルされます.
3、pthread_を呼び出すexit
#include
void pthread_exit(void *rval_ptr)
ここでrval_ptrはタイプレスポインタであり、起動ルーチンパラメータに渡されるのと同様である.同じプロセス内の他のプロセスはpthread_を呼び出すことができます.join関数はこのポインタを取得します.
#include
void pthread_join(pthread_t thread, void **rval_prt);
ここで注意したいのは、スレッドが終了した状態の値であり、スレッドのスタックには使用できません.スタック上でスレッドが終了すると、スタック空間が解放されます.
スレッドは、同じプロセス内の他のスレッドをキャンセルできます.
#include
int pthread_cancel(pthread_t tid)
スレッドは、プロセスのatexitのように、終了時に呼び出されたクリーンアップ関数を登録できます.プロセッサはスタックに記録されます.したがって、呼び出し順序は登録順序とは逆です.
#inlcude
void pthread_cleanup_push(void (*rtn) (void *), void *arg);
void pthread_cleanup_pop(int execute);
コードを書いて、上のいくつかの関数をテストします.
#include<pthread.h>
void cleanup(void *arg)
{
printf("cleanup:%s
",(char *)arg);
}
void* thr_fn1(void *arg)
{
printf("thread 1 start
");
pthread_cleanup_push(cleanup,"thread 1 first handler");
pthread_cleanup_push(cleanup,"thread 1 second handler");
printf("thread 1 push complete
");
if(arg)
pthread_exit((void*)1);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit((void*)1);
}
void* thr_fn2(void *arg)
{
printf("thread 2 start
");
pthread_cleanup_push(cleanup,"thread 2 first handler");
pthread_cleanup_push(cleanup,"thread 2 second handler");
printf("thread 2 push complete
");
if(arg)
return (void*)2;
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return (void*)2;
}
int main(void)
{
pthread_t tid1, tid2;
void *tret;
pthread_create(&tid1,NULL,thr_fn1, (void *)1);// 1
pthread_create(&tid2,NULL,thr_fn2, (void *)1);// 2
//
pthread_join(tid1, &tret);// , 1
printf("thread 1 exit code %d
", (int)tret);// int
pthread_join(tid2, &tret);// , 2
printf("thread 2 exit code %d
", (int)tret);
exit(0);
}
Fedoraでの実行結果は次のとおりです.
thread 2 start thread 2 push complete thread 1 start thread 1 push complete cleanup:thread 1 second handler cleanup:thread 1 first handler thread 1 exit code 1 thread 2 exit code 2