trusty (7) pthreads.7.gz

Provided by: manpages-ja_0.5.0.0.20131015+dfsg-2_all bug

名前

       pthreads - POSIX スレッド

説明

       POSIX.1  は、一般に  POSIX  スレッドや Pthreads として知られる スレッド・プログラミングのインタフェース群
       (関数、ヘッダファイル)  を規定している。一つのプロセスは複数のスレッドを持つことができ、 全てのスレッドは
       同じプログラムを実行する。  これらのスレッドは同じ大域メモリ (データとヒープ領域) を共有するが、 各スレッ
       ドは自分専用のスタック (自動変数) を持つ。

       POSIX.1 はスレッド間でどのような属性を共有するかについても定めている  (つまり、これらの属性はスレッド単位
       ではなくプロセス全体で共通である):

       -  プロセス ID

       -  親プロセス ID

       -  プロセスグループ ID とセッション ID

       -  制御端末

       -  ユーザ ID とグループ ID

       -  オープンするファイルディスクリプタ

       -  レコードのロック (fcntl(3)  参照)

       -  シグナルの配置

       -  ファイルモード作成マスク (umask(2))

       -  カレント・ディレクトリ (chdir(2))  とルート・ディレクトリ (chroot(2))

       -  インターバル・タイマ (setitimer(2))  と POSIX タイマ (timer_create(2))

       -  nice 値 (setpriority(2))

       -  リソース制限 (setrlimit(2))

       -  CPU 時間 (times(2))  とリソース (getrusage(2))  の消費状況の計測

       スタックについても、POSIX.1 はどのような属性が 個々のスレッドで独立に管理されるかを規定している:

       -  スレッド ID (pthread_t データ型)

       -  シグナルマスク (pthread_sigmask(3))

       -  errno 変数

       -  代替シグナルスタック (sigaltstack(2))

       -  リアルタイム・スケジューリングのポリシーと優先度 (sched_setscheduler(2)  と sched_setparam(2))

       以下の Linux 特有の機能もスレッド単位である:

       -  ケーパビリティ (capabilities(7)  参照)

       -  CPU affinity (親和度)  (sched_setaffinity(2))

   pthreads 関数の返り値
       ほとんどの  pthreads  関数は成功すると 0 を返し、 失敗した場合エラー番号を返す。 pthreads 関数は errno を
       セットしない点に注意すること。 POSIX.1-2001 では、 エラーを返す可能性のある pthreads  関数がエラー  EINTR
       で失敗することは決してないと規定している。

   スレッド ID
       あるプロセス内の各スレッドは     (pthread_t     型の)     一意なスレッド識別子を持つ。     この識別子は、
       pthread_create(3) の呼び出し元に返される。また、スレッドは自身のスレッド識別子を pthread_self(3)   を使っ
       て取得できる。  スレッド ID の一意性が保証されるのは、一つのプロセス内においてのみである。 終了したスレッ
       ドが join された後では、スレッド ID は再利用される可能性がある。 スレッド ID を引き数に取る全てのスレッド
       関数において、 その ID は呼び出し元と同じプロセス内の一つのスレッドを参照する。

   スレッドセーフな関数
       スレッドセーフな関数は、複数のスレッドから同時に呼び出しても安全な  (すなわち、同時に呼び出されたかに関わ
       らず、同じ結果を返す) 関数のことである。

       POSIX.1-2001 と POSIX.1-2008では、一部の例外を除き、 標準で規定されている全ての関数がスレッドセーフである
       ことを要求している。 以下の関数が例外である。

           asctime()
           basename()
           catgets()
           crypt()
           ctermid() (NULL でない引き数を渡された場合)
           ctime()
           dbm_clearerr()
           dbm_close()
           dbm_delete()
           dbm_error()
           dbm_fetch()
           dbm_firstkey()
           dbm_nextkey()
           dbm_open()
           dbm_store()
           dirname()
           dlerror()
           drand48()
           ecvt() [POSIX.1-2001 のみ (POSIX.1-2008 で削除された)]
           encrypt()
           endgrent()
           endpwent()
           endutxent()
           fcvt() [POSIX.1-2001 のみ (POSIX.1-2008 で削除された)]
           ftw()
           gcvt() [POSIX.1-2001 のみ (POSIX.1-2008 で削除された)]
           getc_unlocked()
           getchar_unlocked()
           getdate()
           getenv()
           getgrent()
           getgrgid()
           getgrnam()
           gethostbyaddr() [POSIX.1-2001 のみ (POSIX.1-2008 で削除された)]
           gethostbyname() [POSIX.1-2001 のみ (POSIX.1-2008 で削除された)]
           gethostent()
           getlogin()
           getnetbyaddr()
           getnetbyname()
           getnetent()
           getopt()
           getprotobyname()
           getprotobynumber()
           getprotoent()
           getpwent()
           getpwnam()
           getpwuid()
           getservbyname()
           getservbyport()
           getservent()
           getutxent()
           getutxid()
           getutxline()
           gmtime()
           hcreate()
           hdestroy()
           hsearch()
           inet_ntoa()
           l64a()
           lgamma()
           lgammaf()
           lgammal()
           localeconv()
           localtime()
           lrand48()
           mrand48()
           nftw()
           nl_langinfo()
           ptsname()
           putc_unlocked()
           putchar_unlocked()
           putenv()
           pututxline()
           rand()
           readdir()
           setenv()
           setgrent()
           setkey()
           setpwent()
           setutxent()
           strerror()
           strsignal() [POSIX.1-2008 で追加された]
           strtok()
           system() [POSIX.1-2008 で追加された]
           tmpnam() (NULL でない引き数を渡された場合)
           ttyname()
           unsetenv()
           wcrtomb() (最後の引き数が NULL の場合)
           wcsrtombs() (最後の引き数が NULL の場合)
           wcstombs()
           wctomb()

   async-cancel-safe 関数
       async-cancel-safe  関数は、 非同期キャンセル機能が有効になっているアプリケーションで 安全に呼び出すことが
       できる関数のことである (pthread_setcancelstate(3) を参照)。

       以下の関数だけが、POSIX.1-2001 と POSIX.1-2008 で async-cancel-safe で なければならないとされている。

           pthread_cancel()
           pthread_setcancelstate()
           pthread_setcanceltype()

   取り消しポイント (cancellation points)
       POSIX.1 の規定では、特定の関数は取り消しポイントでなければならず、 他の特定の関数は取り消しポイントであっ
       てもよいとされている。   あるスレッドが取り消し可能で、その取り消し種別   (cancelability   type)   が延期
       (deferred) で、そのスレッドに対する取り消し要求が処理待ちの場合、  取り消しポイントである関数を呼び出した
       時点で、そのスレッドのキャンセルが 行われる。

       POSIX.1-2001    と    POSIX.1-2008    の両方、もしくはいずれか一方では、   以下の関数は、取り消しポイント
       (cancellation points) で あることが必須となっている。

           accept()
           aio_suspend()
           clock_nanosleep()
           close()
           connect()
           creat()
           fcntl() F_SETLKW
           fdatasync()
           fsync()
           getmsg()
           getpmsg()
           lockf() F_LOCK
           mq_receive()
           mq_send()
           mq_timedreceive()
           mq_timedsend()
           msgrcv()
           msgsnd()
           msync()
           nanosleep()
           open()
           openat() [POSIX.1-2008 で追加された]
           pause()
           poll()
           pread()
           pselect()
           pthread_cond_timedwait()
           pthread_cond_wait()
           pthread_join()
           pthread_testcancel()
           putmsg()
           putpmsg()
           pwrite()
           read()
           readv()
           recv()
           recvfrom()
           recvmsg()
           select()
           sem_timedwait()
           sem_wait()
           send()
           sendmsg()
           sendto()
           sigpause() [POSIX.1-2001 only (moves to "may" list in POSIX.1-2008)]
           sigsuspend()
           sigtimedwait()
           sigwait()
           sigwaitinfo()
           sleep()
           system()
           tcdrain()
           usleep() [POSIX.1-2001 のみ (POSIX.1-2008 で削除された)]
           wait()
           waitid()
           waitpid()
           write()
           writev()

       POSIX.1-2001   と    POSIX.1-2008    の両方、もしくはいずれか一方では、    以下の関数は、取り消しポイント
       (cancellation points) で あってもよいことになっている。

           access()
           asctime()
           asctime_r()
           catclose()
           catgets()
           catopen()
           chmod() [POSIX.1-2008 で追加された]
           chown() [POSIX.1-2008 で追加された]
           closedir()
           closelog()
           ctermid()
           ctime()
           ctime_r()
           dbm_close()
           dbm_delete()
           dbm_fetch()
           dbm_nextkey()
           dbm_open()
           dbm_store()
           dlclose()
           dlopen()
           dprintf() [POSIX.1-2008 で追加された]
           endgrent()
           endhostent()
           endnetent()
           endprotoent()
           endpwent()
           endservent()
           endutxent()
           faccessat() [POSIX.1-2008 で追加された]
           fchmod() [POSIX.1-2008 で追加された]
           fchmodat() [POSIX.1-2008 で追加された]
           fchown() [POSIX.1-2008 で追加された]
           fchownat() [POSIX.1-2008 で追加された]
           fclose()
           fcntl() (cmd 引き数が何であっても)
           fflush()
           fgetc()
           fgetpos()
           fgets()
           fgetwc()
           fgetws()
           fmtmsg()
           fopen()
           fpathconf()
           fprintf()
           fputc()
           fputs()
           fputwc()
           fputws()
           fread()
           freopen()
           fscanf()
           fseek()
           fseeko()
           fsetpos()
           fstat()
           fstatat() [POSIX.1-2008 で追加された]
           ftell()
           ftello()
           ftw()
           futimens() [POSIX.1-2008 で追加された]
           fwprintf()
           fwrite()
           fwscanf()
           getaddrinfo()
           getc()
           getc_unlocked()
           getchar()
           getchar_unlocked()
           getcwd()
           getdate()
           getdelim() [POSIX.1-2008 で追加された]
           getgrent()
           getgrgid()
           getgrgid_r()
           getgrnam()
           getgrnam_r()
           gethostbyaddr() [SUSv3 のみ (この関数は POSIX.1-2008 で削除されている)]
           gethostbyname() [SUSv3 のみ (この関数は POSIX.1-2008 で削除されている)]
           gethostent()
           gethostid()
           gethostname()
           getline() [POSIX.1-2008 で追加された]
           getlogin()
           getlogin_r()
           getnameinfo()
           getnetbyaddr()
           getnetbyname()
           getnetent()
           getopt() (opterr が 0 以外の場合)
           getprotobyname()
           getprotobynumber()
           getprotoent()
           getpwent()
           getpwnam()
           getpwnam_r()
           getpwuid()
           getpwuid_r()
           gets()
           getservbyname()
           getservbyport()
           getservent()
           getutxent()
           getutxid()
           getutxline()
           getwc()
           getwchar()
           getwd() [SUSv3 のみ (この関数は POSIX.1-2008 で削除されている)]
           glob()
           iconv_close()
           iconv_open()
           ioctl()
           link()
           linkat() [POSIX.1-2008 で追加された]
           lio_listio() [POSIX.1-2008 で追加された]
           localtime()
           localtime_r()
           lockf() [POSIX.1-2008 で追加された]
           lseek()
           lstat()
           mkdir() [POSIX.1-2008 で追加された]
           mkdirat() [POSIX.1-2008 で追加された]
           mkdtemp() [POSIX.1-2008 で追加された]
           mkfifo() [POSIX.1-2008 で追加された]
           mkfifoat() [POSIX.1-2008 で追加された]
           mknod() [POSIX.1-2008 で追加された]
           mknodat() [POSIX.1-2008 で追加された]
           mkstemp()
           mktime()
           nftw()
           opendir()
           openlog()
           pathconf()
           pclose()
           perror()
           popen()
           posix_fadvise()
           posix_fallocate()
           posix_madvise()
           posix_openpt()
           posix_spawn()
           posix_spawnp()
           posix_trace_clear()
           posix_trace_close()
           posix_trace_create()
           posix_trace_create_withlog()
           posix_trace_eventtypelist_getnext_id()
           posix_trace_eventtypelist_rewind()
           posix_trace_flush()
           posix_trace_get_attr()
           posix_trace_get_filter()
           posix_trace_get_status()
           posix_trace_getnext_event()
           posix_trace_open()
           posix_trace_rewind()
           posix_trace_set_filter()
           posix_trace_shutdown()
           posix_trace_timedgetnext_event()
           posix_typed_mem_open()
           printf()
           psiginfo() [POSIX.1-2008 で追加された]
           psignal() [POSIX.1-2008 で追加された]
           pthread_rwlock_rdlock()
           pthread_rwlock_timedrdlock()
           pthread_rwlock_timedwrlock()
           pthread_rwlock_wrlock()
           putc()
           putc_unlocked()
           putchar()
           putchar_unlocked()
           puts()
           pututxline()
           putwc()
           putwchar()
           readdir()
           readdir_r()
           readlink() [POSIX.1-2008 で追加された]
           readlinkat() [POSIX.1-2008 で追加された]
           remove()
           rename()
           renameat() [POSIX.1-2008 で追加された]
           rewind()
           rewinddir()
           scandir() [POSIX.1-2008 で追加された]
           scanf()
           seekdir()
           semop()
           setgrent()
           sethostent()
           setnetent()
           setprotoent()
           setpwent()
           setservent()
           setutxent()
           sigpause() [POSIX.1-2008 で追加された]
           stat()
           strerror()
           strerror_r()
           strftime()
           symlink()
           symlinkat() [POSIX.1-2008 で追加された]
           sync()
           syslog()
           tmpfile()
           tmpnam()
           ttyname()
           ttyname_r()
           tzset()
           ungetc()
           ungetwc()
           unlink()
           unlinkat() [POSIX.1-2008 で追加された]
           utime() [POSIX.1-2008 で追加された]
           utimensat() [POSIX.1-2008 で追加された]
           utimes() [POSIX.1-2008 で追加された]
           vdprintf() [POSIX.1-2008 で追加された]
           vfprintf()
           vfwprintf()
           vprintf()
           vwprintf()
           wcsftime()
           wordexp()
           wprintf()
           wscanf()

       実装時に、標準規格で規定されていないその他の関数を取り消しポイント  とすることも認められている。 特に、停
       止 (block) する可能性がある非標準の関数を取り消しポイントと する実装はあり得ることだろう  (ファイルを扱う
       可能性のあるほとんどの関数がこれに含まれる)。

   Linux でのコンパイル
       Linux では、Pthreads API を用いたプログラムは cc -pthread でコンパイルすべきである。

   POSIX スレッドの Linux での実装
       これまで、2つのスレッドの実装が Linux の GNU C ライブラリにより 提供されてきた。

       LinuxThreads
              最初の Pthreads の実装。 glibc 2.4 以降は、この実装はもはやサポートされていない。

       NPTL (Native POSIX Threads Library)
              新しい  Pthreads  の実装。LinuxThreads と比べると、 NPTL は POSIX.1 の要求仕様への準拠の度合いが高
              く、 多数のスレッドを作成した際の性能も高い。 NPTL は glibc 2.3.2 以降で利用可能である。 NPTL を利
              用するには Linux 2.6 カーネルに実装されている機能が必要である。

       どちらの実装もいわゆる  1:1 実装、すなわち個々のスレッドが カーネルのスケジューリング実体にマッピングされ
       る。 どちらのスレッドの実装も Linux の clone(2)  システムコールを利用している。 NPTL では、スレッド同期の
       基本機構 (mutex や スレッドの join 等) は Linux の futex(2)  システムコールを使って実装されている。

   LinuxThreads
       この実装の大きな特徴は以下の通りである:

       -  メインスレッド  (最初のスレッド) とプログラムが pthread_create(3)  を使って作成したスレッドに加え、 こ
          の実装では「管理 (manager)」スレッドが作成される。 管理スレッドはスレッドの作成と終了を取り扱う  (この
          スレッドがうっかり kill されると、問題が起こることがある)。

       -  この実装では内部でシグナルを使用している。  Linux 2.2 以降では、リアルタイムシグナルのうち最初の 3つが
          使われる (signal(7) 参照)。 それ以前のカーネルでは SIGUSR1SIGUSR2  が使われる。  アプリケーション
          は、スレッド実装で利用されているシグナルを どれも使わないようにしなければならない。

       -  スレッド間でプロセス ID を共有しない (実際には LinuxThreads のスレッドは通常よりは情報を共有するプロセ
          スとして   実装されているが、一つの共通のプロセス   ID   を共有してはいない)。    (管理スレッドを含む)
          LinuxThreads スレッドは ps(1) を使うと別のプロセスのように見える。

       LinuxThreads の実装では POSIX.1 仕様から逸脱している点が いくつかある。以下に示すような点がある:

       -  getpid(2)  を呼び出したときに、スレッド毎に異なる値が返される。

       -  メインスレッド以外のスレッドで  getppid(2)   を呼び出すと、管理スレッドのプロセス ID が返される。 本当
          は、これらのスレッドで getppid(2)  を呼んだ場合にはメインスレッドでの getppid(2)  と同じ値が返るべきで
          ある。

       -  あるスレッドが   fork(2)    を使って新しい子プロセスを作成した場合、  どのスレッドでもこの子プロセスを
          wait(2) できるべきである。しかしながら、この実装では子プロセスを作成した  スレッドだけがこの子プロセス
          を wait(2)  できる。

       -  あるスレッドが execve(2)  を呼び出した場合、他のスレッドは全て終了される (POSIX.1 の仕様通り)。 しかし
          ながら、新しいプロセスは execve(2)  を呼んだスレッドと同じ PID  を持つ。正しくは  メインスレッドと同じ
          PID を持つべきである。

       -  スレッド間でユーザ  ID とグループ ID が共有されない このことは、set-user-ID プログラムで面倒な事態を招
          いたり、 アプリケーションが seteuid(2)  などを使って信用情報 (credentials)  を変更した場合に  Pthreads
          関数が失敗する原因となる。

       -  スレッド間で共通のセッション ID やプロセスグループ ID を共有しない。

       -  スレッド間で fcntl(2)  を使って作成されるレコード・ロックを共有しない。

       -  times(2)  と getrusage(2)  が返す情報がプロセス全体の情報でなくスレッド単位の情報である。

       -  スレッド間でセマフォのアンドゥ値 (semop(2)  参照) を共有しない。

       -  スレッド間でインターバル・タイマを共有しない。

       -  スレッドは共通の nice 値を共有しない。

       -  POSXI.1  では、全体としてのプロセスに送られるシグナルと、 個別のスレッドに送られるシグナルを区別して考
          えている。 POSIX.1 によると、プロセスに送られたシグナル (例えば kill(2)  を使って送る)  は、そのプロセ
          スに属すスレッドのうち  勝手に (arbitrarily) に選択された一つのスレッドにより処理される ことになってい
          る。LinuxThreads はプロセスに送られるシグナルの 概念に対応しておらず、シグナルは特定のスレッドにだけ送
          ることができる。

       -  スレッドはそれぞれの独自の代替シグナルスタックの設定を持つ。    しかし、新しいスレッドの代替シグナルス
          タックの設定は そのスレッドを作成したスレッドからコピーされ、そのため スレッドは最初は一つの代替シグナ
          ルスタックを共有する。  (仕様では、新しいスレッドは代替シグナルスタックが定義されていない状態 で開始さ
          れるべきとされている。  2つのスレッドが共有されている代替シグナルスタック上で同時に   シグナルの処理を
          行った場合、予測不可能なプログラムのエラーが 起こり得る。)

   NPTL
       NPTL  では、一つのプロセスの全てのスレッドは同じスレッド・グループ  に属する;  スレッド・グループの全メン
       バーは同じ PID を共有する。 NPTL は管理スレッド (manager thread) を利用しない。 NPTL は内部でリアルタイム
       シグナルのうち最初の  2つの番号を使用しており (signal(7)  参照)、これらのシグナルはアプリケーションでは使
       用できない。

       NPTL にも POSIX.1 に準拠していない点が少なくとも一つある:

       -  スレッドは共通の nice 値を共有しない。

       NPTL の標準非準拠な点のうちいくつかは以前のカーネルでのみ発生する:

       -  times(2)   と  getrusage(2)   が返す情報がプロセス全体の情報でなくスレッド単位の情報である   (カーネル
          2.6.9 で修正された)。

       -  スレッド間でリソース制限を共有しない (カーネル 2.6.10 で修正された)。

       -  スレッド間でインターバル・タイマを共有しない (カーネル 2.6.12 で修正された)。

       -  メインスレッドだけが setsid(2)  を使って新しいセッションを開始することができる (カーネル 2.6.16 で修正
          された)。

       -  メインスレッドだけが setpgid(2)   を使ってそのプロセスをプロセス・グループ・リーダーにすることができる
          (カーネル 2.6.16 で修正された)。

       -  スレッドはそれぞれの独自の代替シグナルスタックの設定を持つ。    しかし、新しいスレッドの代替シグナルス
          タックの設定は そのスレッドを作成したスレッドからコピーされ、そのため スレッドは最初は一つの代替シグナ
          ルスタックを共有する (カーネル 2.6.16 で修正された)。

       NPTL の実装では以下の点についても注意すること:

       -  スタックサイズのリソースのソフト・リミット  (setrlimit(2)   の RLIMIT_STACK の説明を参照) が unlimited
          以外の値に設定されている場合、ソフト・リミットの値が    新しいスレッドのデフォルトのスタックサイズとな
          る。 設定を有効にするためには、プログラムを実行する前にリミット値を 設定しておかなければならない。たい
          ていは、シェルの組み込みコマンドの ulimit -s (C シェルでは limit stacksize)  を使って設定する。

   スレッド実装の判定
       glibc 2.3.2 以降では、 getconf(1)  コマンドを使って、 システムのスレッド実装を判定することができる。 以下
       に例を示す:

           bash$ getconf GNU_LIBPTHREAD_VERSION
           NPTL 2.3.4

       ぞれ以前の  glibc  のバージョンでは、以下のようなコマンドで  デフォルトのスレッド実装を判定することができ
       る。

           bash$ $( ldd /bin/ls | grep libc.so | awk '{print $3}' ) | \
                           egrep -i 'threads|ntpl'
                   Native POSIX Threads Library by Ulrich Drepper et al

   スレッドの実装の選択: LD_ASSUME_KERNEL
       LinuxThreads と NPTL の両方をサポートしている glibc (glibc 2.3.x)  があるシステムでは、  LD_ASSUME_KERNEL
       環境変数を使うことで、動的リンカがデフォルトで  選択するスレッド実装を上書きすることができる。 この変数に
       より、動的リンカが特定のバージョンのカーネル上で 動作していると仮定するように指定する。 NPTL が必要とする
       サポート機能を提供していないカーネルバージョンを 指定することで、強制的に LinuxThreads を使うことができる
       (このようなことをする最もありそうな場面は、 LinuxThreads の標準非準拠な振舞いに依存する  (壊れた)  アプリ
       ケーション を動作させる場合だろう)。 以下に例を示す:

           bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \
                           awk '{print $3}' ) | egrep -i 'threads|ntpl'
                   linuxthreads-0.10 by Xavier Leroy

関連項目

       clone(2), futex(2), gettid(2), futex(7), sigevent(7), signal(7),

       pthreads の各種マニュアルページ、例えば: pthread_attr_init(3), pthread_atfork(3), pthread_cancel(3),
       pthread_cleanup_push(3), pthread_cond_signal(3), pthread_cond_wait(3), pthread_create(3),
       pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_key_create(3), pthread_kill(3),
       pthread_mutex_lock(3), pthread_mutex_unlock(3), pthread_once(3), pthread_setcancelstate(3),
       pthread_setcanceltype(3), pthread_setspecific(3), pthread_sigmask(3), pthread_sigqueue(3), and
       pthread_testcancel(3)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 3.54 の一部 である。プロジェクトの説明とバグ報告
       に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。