書式
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
-pthread を付けてコンパイルとリンクを行う。
説明
pthread_create() 関数は、呼び出したプロセス内に新しいスレッドを作成する。 新しいスレッドの実行は、 start_routine() を起動することで開始される。 start_routine() は引き数を一つだけ取り、 arg が start_routine() の引き数として渡される。新しく作成されたスレッドは、以下のいずれかで終了する。
- *
- スレッドが pthread_exit(3) を呼び出す。 pthread_exit(3) を呼び出す際には終了ステータス値を指定する。 この値は pthread_join(3) を呼び出した同じプロセス内の 別のスレッドで参照できる。
- *
- スレッドが start_routine() から返る。これは、 return 文に渡した値で pthread_exit(3) を呼び出すのと等価である。
- *
- スレッドがキャンセルされる (pthread_cancel(3) 参照)。
- *
- プロセス内のいずれかのスレッドで exit(3) が呼ばれるか、 メインスレッドで main() 内で return が実行される。 この場合は、プロセス内の全てのスレッドが終了される。
attr 引き数は pthread_attr_t 構造体へのポインタであり、 pthread_attr_t 構造体の内容を使用して、スレッド作成時に 新しいスレッドの属性が決定される。 この構造体は pthread_attr_init(3) や関連の関数を使って初期化される。 attr が NULL の場合、新しいスレッドはデフォルトの属性で作成される。
成功した場合は、 pthread_create() は返る前に新しいスレッドの ID を thread が指すバッファに格納する。この ID は、これ以降に他の pthreads 関数の呼び出しでスレッドを参照するのに使用される。
新しいスレッドは、スレッドを作成したスレッドのシグナルマスク (pthread_sigmask(3) 参照) のコピーを継承する。 新しいスレッドの処理待ちシグナル (sigpending(2)) の集合は空となる。 新しいスレッドはスレッドを作成したスレッドの代替シグナルスタック (sigaltstack(2)) を継承しない。
新しいスレッドは呼び出したスレッドの浮動小数点環境 (fenv(3)) を継承する。
新しいスレッドの CPU 時間時計の初期値は 0 である (pthread_getcpuclockid(3) 参照)。
Linux 固有の詳細
新しいスレッドは、呼び出したスレッドの ケーパビリティセット (capabilities(7) 参照) と CPU affinity マスク (sched_setaffinity(2) 参照) の コピーをを継承しない。返り値
成功すると、 pthread_create() は 0 を返す。 エラーの場合は、エラー番号が返され、 *thread の内容は不定である。エラー
- EAGAIN
- 別のスレッドを作成するのに十分なリソースがないか、システムで設定された スレッド数の上限に達していた。後者が起こるのは 2 つの場合がある。 一つは、実ユーザ ID 当たりのプロセス数の上限である、RLIMIT_NPROC ソフトリソース上限 (setrlimit(2) で設定できる) に達していた場合 である。もう一つはカーネルのシステム全体のスレッド数の上限である /proc/sys/kernel/threads-max が達していた場合である。
- EINVAL
- attr で指定された設定が不正である。
- EPERM attr に指定されたスケジューリングポリシーとパラメータを 設定する許可がない。
準拠
POSIX.1-2001.注意
pthread_create() が *thread で返すスレッド ID についての 詳しい情報は pthread_self(3) を参照のこと。 リアルタイムスケジューリングポリシーが使用されない限り、 pthread_create() の呼び出し後に、 どのスレッドが---呼び出したスレッドか新しいスレッドか--- 次に実行されるかは決まっていない。スレッドは join 可能か detached (切り離された状態) のどちらかに することができる。スレッドが join 可能な場合、別のスレッドが pthread_join(3) を使って終了したスレッドを待ち、終了ステータスを取得 することができる。終了した join 可能なスレッドは join された場合にのみ、 そのスレッドの最後に残ったリソースが解放されシステムに戻される。 detached 状態のスレッドが終了すると、そのスレッドのリソースは自動的に システムに戻される。detached 状態のスレッドを join して、その終了 ステータスを取得することはできない。スレッドを detached 状態にするのは、 その終了ステータスをアプリケーションが気にする必要がないある種の デーモン (daemon) スレッドでは有用である。 デフォルトでは、新しいスレッドは join 可能な状態で作成される。 (pthread_attr_setdetachstate(3) を使って) attr でスレッドが detached 状態で作成されるように設定されていない限り、join 可能な状態で 作成される。
Linux/x86-32 では、新しいスレッドのデフォルトのスタックサイズは 2MB で ある。NPTL スレッド実装の下では、プログラム開始時の RLIMIT_STACK ソフトリソース上限が"unlimited" 以外の場合、その値が新しいスレッドのデ フォルトのスタックサイズとなる。 pthread_attr_setstacksize(3) を使って、スレッドを作成する際の attr 引き数に明示的にスタックサイズ属性を設定することで、 デフォルト値以外のスタックサイズを得ることができる。
バグ
廃止予定の LinuxThreads 実装では、プロセス内の各スレッドは異なる プロセス ID を持つ。これは POSIX スレッドの規格に違反しており、 他の多くの標準非準拠の点の原因になっている。 pthreads(7) を参照のこと。例
以下のプログラムは、 pthread_create() や pthreads API の他のいろいろな関数の使用例を示している。以下の実行例は、 NPTL スレッド実装が提供されているシステムでのもので、 スタックサイズがデフォルト値の "stack size" リソース上限で指定される値 になる。
$ ulimit -s 8192 # The stack size limit is 8 MB (0x800000 bytes) $ ./a.out hola salut servus Thread 1: top of stack near 0xb7dd03b8; argv_string=hola Thread 2: top of stack near 0xb75cf3b8; argv_string=salut Thread 3: top of stack near 0xb6dce3b8; argv_string=servus Joined with thread 1; returned value was HOLA Joined with thread 2; returned value was SALUT Joined with thread 3; returned value was SERVUS
次の実行例では、プログラム内で、作成されるスレッドに対して (pthread_attr_setstacksize(3) を使って1MB のスタックサイズを 明示的に設定している。
$ ./a.out -s 0x100000 hola salut servus Thread 1: top of stack near 0xb7d723b8; argv_string=hola Thread 2: top of stack near 0xb7c713b8; argv_string=salut Thread 3: top of stack near 0xb7b703b8; argv_string=servus Joined with thread 1; returned value was HOLA Joined with thread 2; returned value was SALUT Joined with thread 3; returned value was SERVUS
プログラムのソース
#include <pthread.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <ctype.h> #define handle_error_en(en, msg) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) struct thread_info { /* Used as argument to thread_start() */ pthread_t thread_id; /* ID returned by pthread_create() */ int thread_num; /* Application-defined thread # */ char *argv_string; /* From command-line argument */ }; /* Thread start function: display address near top of our stack, and return upper-cased copy of argv_string */ static void * thread_start(void *arg) { struct thread_info *tinfo = arg; char *uargv, *p; printf("Thread %d: top of stack near %p; argv_string=%s\n", tinfo->thread_num, &p, tinfo->argv_string); uargv = strdup(tinfo->argv_string); if (uargv == NULL) handle_error("strdup"); for (p = uargv; *p != '\0'; p++) *p = toupper(*p); return uargv; } int main(int argc, char *argv[]) { int s, tnum, opt, num_threads; struct thread_info *tinfo; pthread_attr_t attr; int stack_size; void *res; /* The "-s" option specifies a stack size for our threads */ stack_size = -1; while ((opt = getopt(argc, argv, "s:")) != -1) { switch (opt) { case 's': stack_size = strtoul(optarg, NULL, 0); break; default: fprintf(stderr, "Usage: %s [-s stack-size] arg...\n", argv[0]); exit(EXIT_FAILURE); } } num_threads = argc - optind; /* Initialize thread creation attributes */ s = pthread_attr_init(&attr); if (s != 0) handle_error_en(s, "pthread_attr_init"); if (stack_size > 0) { s = pthread_attr_setstacksize(&attr, stack_size); if (s != 0) handle_error_en(s, "pthread_attr_setstacksize"); } /* Allocate memory for pthread_create() arguments */ tinfo = calloc(num_threads, sizeof(struct thread_info)); if (tinfo == NULL) handle_error("calloc"); /* Create one thread for each command-line argument */ for (tnum = 0; tnum < num_threads; tnum++) { tinfo[tnum].thread_num = tnum + 1; tinfo[tnum].argv_string = argv[optind + tnum]; /* The pthread_create() call stores the thread ID into corresponding element of tinfo[] */ s = pthread_create(&tinfo[tnum].thread_id, &attr, &thread_start, &tinfo[tnum]); if (s != 0) handle_error_en(s, "pthread_create"); } /* Destroy the thread attributes object, since it is no longer needed */ s = pthread_attr_destroy(&attr); if (s != 0) handle_error_en(s, "pthread_attr_destroy"); /* Now join with each thread, and display its returned value */ for (tnum = 0; tnum < num_threads; tnum++) { s = pthread_join(tinfo[tnum].thread_id, &res); if (s != 0) handle_error_en(s, "pthread_join"); printf("Joined with thread %d; returned value was %s\n", tinfo[tnum].thread_num, (char *) res); free(res); /* Free memory allocated by thread */ } free(tinfo); exit(EXIT_SUCCESS); }
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。