名 前
pthread_create − 新 し い ス レ ッ ド を 作 成 す る
書 式
#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 別 の ス レ ッ ド を 作 成 す る の に 十 分 な リ ソ ー ス が な い 。
EAGAIN シ ス テ ム で 設 定 さ れ た ス レ ッ ド 数 の 上 限 に 達 し て い た 。 こ の エ ラ ー の 原 因 と な る 上 限 値 は い く つ か あ る 。 実 ユ ー ザ ー
ID 当 た り の プ ロ セ ス 数 と ス レ ッ ド 数 の 上 限 で あ る 、 ソ フ ト リ ソ ー ス 上 限 RLIMIT_NPROC に 達 し て い た (setrlimit(2) で 設 定 で き る )。 カ ー ネ ル の シ ス テ ム 全 体 の プ ロ セ ス と ス レ ッ ド の 数 の 上 限 値 で あ る /proc/sys/kernel/threads−max が 達 し て い た (proc(5) 参 照 )。 PID の 最 大 値 /proc/sys/kernel/pid_max に 達 し て い た (proc(5) 参 照 )。
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); }
関 連 項 目
getrlimit(2), pthread_attr_init(3), pthread_cancel(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_getattr_np(3), pthread_join(3), pthread_self(3), pthreads(7)
こ の 文 書 に つ い て
こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。