本文に進む 日本−日本語
日本HPホーム 製品とサービス お客様サポート/ ダウンロード ソリューション ご購入の方法
≫ お問い合わせ
詳細検索オプション
日本HPホーム
HP-UX リファレンス: セクション 3 : ライブラリ (N~Z) > p

pthread(3T)

pthread ライブラリ
HP-UX 11i Version 2: September 2004
≫ 

テクニカル ドキュメント

PDF版
フィードバック
ここから本文が始まります

 ≫ 目次

 ≫ 索引

名称

pthread ― POSIX.1c でのスレッドの概要

説明

HP で開発した POSIX.1c のライブラリにより、アプリケーションおよびマルチプロセッサプラットフォームの並列処理を利用できるプロセスの作成が可能になります。pthread ライブラリ libpthread は、90 以上の標準化されたインタフェースで構成され、並列のアプリケーションの開発とそれらの処理をプロセス内またはプロセス間で同期させることが可能です。このマンページでは、libpthread の用語およびスレッドを使用するプログラムのコンパイルおよびリンクの方法を含む概要を説明します。

コンパイルの概要

マルチスレッドのアプリケーションでは、コンパイル時に適切な POSIX リビジョンレベル (199506) を定義して、-lpthread により pthread ライブラリにリンクしなければなりません。例:

cc -D_POSIX_C_SOURCE=199506L -o myapp myapp.c -lpthread

すべてのプログラムソースには、ヘッダーファイル <pthread.h> が含まれていなければなりません。

注記: ("-Aa" を指定して) ANSI コンパイルを明示的に指定する場合、POSIX リビジョンレベルを定義すると、プログラムは POSIX ネームスペース内のインタフェースだけを使用します。より大きな X/Open ネームスペース内のインタフェースが呼び出される場合には、-D_POSIX_C_SOURCE=199506L の他に、-D_XOPEN_SOURCE_EXTENDED または -D_HPUX_SOURCE のいずれかのコンパイラオプションの指定が必要です。-Ae を指定して (あるいは "-A" を指定せずに) コンパイルすると、-D_HPUX_SOURCE が暗黙的に指定されます。

注記: 一部のドキュメンテーションでは、コンパイルに -D_REENTRANT を使用するようにお薦めしています。これも正しく機能しますが、旧形式であると考えられます。

スレッドの概要

スレッド は、プロセス内の独立した制御の流れであり、コンテキスト (レジスタセットおよびプログラムカウンターを含む) および一連の実行命令で構成されます。

すべてのプロセスは、最低でも 1 つのスレッドで構成され、マルチスレッドプロセスは複数のスレッドで構成されています。すべてのスレッドは、そのプログラムに割り当てられた共通アドレス空間を共有します。POSIX pthread の API を使用するプログラムは、 ユーザースレッド と呼ばれるものを作成し処理します。 カーネル スレッドは、カーネルがスケジューリングできるエンティティであり、1 つまたは複数のユーザースレッドをサポートすることができます。 HP-UX リリース 11i バージョン 1.6 以降では、HP-UX のスレッドの実装では、ユーザースレッドとカーネルスレッド間で、1 対 1 のマッピングだけでなく N 対 1 のマッピングもサポートしています。

各スレッドには、作成時に pthread_t 型の固有の識別子が割り当てられます。スレッド id は、プロセス専用の値であり、処理系に依存します。この値はスレッドにとって不明瞭なハンドルとみなされますのでアプリケーションでは使用しないでください。

インタフェースに関する注記

HP-UX システムでは、pthread の API への標準的でない拡張をいくつか行っています。これらの拡張には、他と区別するために、常に _np または _NP (non-portable) という接尾辞が付いています。

プログラマは、使用する関数について必ずマンページを調べてください。標準的に指定される関数の中には、使用できないものや、一部の処理系では効果がないものがあります。

スレッドの作成/消去

プログラムは、 pthread_create() 関数を使用してスレッドを作成します。スレッドは、その作業を終了したときに、 pthread_exit() 関数を呼び出してもかまいませんし、単にその最初の関数から戻ってもかまいません。 スレッドは、 pthread_join() 関数を使用することによって、他のスレッドの完了を検出することができます。

pthread_create() 

スレッドを作成し、固有の識別子 pthread_t を割り当てます。 呼び出し元は、そのスレッドによって実行される関数を与えます。この場合、任意でそのスレッドの属性を明示的に指定することができます (後で説明する 『PTHREAD ATTRIBUTES』 を参照してください)。

pthread_exit() 

完了時にスレッドによって呼び出されます。この関数は戻りません。

pthread_join() 

これは、 wait() に似ていますが、pthreads 用のものです。スレッドはプロセス内で他のスレッドと結合する可能性がありますが、親子関係はありません。これは、指定されたスレッドが終了した時点で戻り、そのスレッドの資源が取得されます。

pthread_detach() 

スレッドの「結合」を不要にします。スレッドの資源はそのスレッドが終了した時点でシステムによって取得されます。

PTHREAD の属性

スレッド属性の集合を pthread_create() に与えることができます。 デフォルト値の変更は、すべて pthread_create() の呼び出しを行う前に、属性集合に対して行わなければなりません。この呼び出しの後に属性集合を変更しても、作成されたスレッドには影響を与えません。ただし、属性集合は複数の pthread_create() の呼び出しで使用することができます。

スレッドの "detachstate"、"schedparam"、"schedpolicy"、および "processor" 属性だけは、スレッド作成の後に影響を受ける可能性があることに注意してください。ただしこれらの属性は、それぞれ、 pthread_detach()pthread_setschedparam() および pthread_processor_bind_np() 関数によって変更されます。

pthread_attr_init()
  

pthread_create() 呼び出し内で使用するために属性集合を初期化します。

pthread_attr_destroy()
  

属性集合の内容を消去します。

pthread_attr_getdetachstate(),
pthread_attr_getguardsize(),
pthread_attr_getinheritsched(),
pthread_attr_getprocessor_np(),
pthread_attr_getschedparam(),
pthread_attr_getschedpolicy(),
pthread_attr_getscope(),
pthread_attr_getstackaddr(),
pthread_attr_getstacksize(),
pthread_attr_setdetachstate(),
pthread_attr_setguardsize(),
pthread_attr_setinheritsched(),
pthread_attr_setprocessor_np(),
pthread_attr_setschedparam(),
pthread_attr_setschedpolicy(),
pthread_attr_setscope(),
pthread_attr_setstackaddr(),
pthread_attr_setstacksize()

  • これらの pthread_attr_get/set attribute () 関数は、属性集合内の該当する属性を取得/設定します。 スレッド属性の説明については、これらの関数に関するマンページを参照してください。

    pthread_default_stacksize_np()
      

    これは、後続の属性集合の初期化 (pthread_attr_init() の呼び出し)、または属性が与えられていない場合の pthread_create() で作成されるスレッドのデフォルトのスタックサイズを設定するために使用します。

キャンセル

一部のアプリケーションでは、プロセス全体を終了することなく、特定のスレッドを終了することを要求する場合があります。キャンセル対象スレッドがシステムコールまたは特定のライブラリルーチンを実行している間に、そのスレッドが同じプロセス内の別のスレッドによってキャンセルされる可能性があります。

あるスレッドが別のスレッドに対してキャンセル要求を発行する場合、キャンセル対象スレッドは、 pthread_testcancel() インタフェースによって、保留中のキャンセル要求があるかどうかをチェックすることができます。保留中のキャンセル要求によって呼び出された場合、キャンセル対象スレッドは、インストールされたすべてのクリーンアップハンドラーを実行した後に終了します。クリーンアップハンドラーは、このキャンセルされるスレッドによって割り当てられている動的記憶領域を削除したり、mutex ロックを解除したり、またはその他の処理のために使用されます。

一般に、スレッドのキャンセルタイプは、 deferred です。 つまりキャンセル要求は、そのスレッドがライブラリ関数またはシステムコールのリスト (下記のリストを参照) の 1 つである キャンセル ポイントに到達するまで、保留状態のままです。

スレッドは、そのキャンセルタイプを非同期 に設定することができます。この場合、キャンセル要求はその時点で処理されます。 これは、キャンセルポイントとなる関数を呼び出さないコンピュートバウンドのスレッド内で効果的に使用することができます。

pthread_cancel() 

指定したスレッドの実行をキャンセルます。

pthread_testcancel()
  

スレッドによって呼び出され、保留中のキャンセル要求を処理します。

pthread_setcancelstate(),
pthread_setcanceltype()

  • スレッドに対するキャンセルの特性を設定します。 有効または無効、あるいは同期的または延期を設定することができます。

pthread_cleanup_pop(),
pthread_cleanup_push()

  • キャンセルクリーンアップ ハンドラーを登録または消去します。

pthread ライブラリ、システム関数、libc でのキャンセルポイントのリストについては、 thread_safety(5) を参照してください。

libc 関数の場合、スレッドがキャンセルされるかどうかは、関数の実行中にどのような処理が行われたかによって決まります。 スレッドが関数内部でブロックした場合、キャンセルポイントが作成されます (つまり、そのスレッドはキャンセルされる可能性があります)。 その他のライブラリでも、キャンセルポイントがあることがあります。 詳細は、ライブラリに添付されているドキュメントを参照してください。

キャンセルポイントのリストは、リリースごとに異なります。 一般に、関数が EINTR エラーで戻る場合は、その関数がキャンセルポイントとなる可能性があります。

スケジューリング

スレッドは個々にそれぞれのスケジューリング方針および優先順位を制御することができます。スレッドは、そのスレッドの実行、または他のスレッドの実行を一時停止することもできます。つまり、スレッドにはプロセッサの資源の割り当ての他にいくつかの制御が与えられています。

pthread_suspend()
  

この関数は、一時的にスレッドの実行を停止するために使用されます。

pthread_continue(),
pthread_resume_np()

  • これらの関数によって、以前に一時停止されていたスレッドの実行が継続します。

pthread_num_processor_np(),
pthread_processor_bind_np(),
pthread_processor_id_np()

  • これらの関数は、プロセッサの構成を調べたり、スレッドを特定のプロセッサにバインドしたりするために使用されます。

pthread_getconcurrency(),
pthread_setconcurrency()

  • これらの関数は、境界のないスレッドに対して実際の並列処理を制御するために使用されます。

pthread_getschedparam(),
pthread_setschedparam()

  • これらの関数は、スレッドのスケジューリング方針および優先順位を操作するために使用されます。

sched_get_priority_max(),
sched_get_priority_min()

  • これらの関数は、指定したスケジューリング方針の優先順位の範囲を調べるために使用されます。

    sched_yield 

    この関数は、スレッドによって使用され、優先順位が等しいかまたは大きな他のスレッドにプロセッサを渡します。

通信および同期化

マルチスレッドのアプリケーションは、並列に複数の命令を実行します。 プロセス全体にわたる (またはプロセス内の) 共有資源 (メモリー、ファイル記述子など) へのアクセスには、スレッド間の調整つまり同期のための制御が必要です。 libpthread ライブラリは、決定性アプリケーションを作成するために必要な同期的基本関数を提供します。マルチスレッドのアプリケーションは、強制的に非同期スレッドのコンテキストを同期させたり、順番に実行したり、実行中に管理および処理されるデータ構造および資源にアクセスしたりすることによって、決定性を保証します。これらは、相互排他 (mutex) ロック、条件変数、および読み込み/書き込みロックです。HP-UX オペレーティングシステムでも、POSIX セマフォを提供しています (次の項を参照してください)。

Mutexes は、並列して行われる変更からデータ構造を排他的に保護する手段を与えます。それらのプロトコルは、ロックを行っているスレッドが類似の mutex のロックを解除するまで、保護された構造内容が変更されるのを妨ぐことができます。mutex は、 pthread_mutex_init() の呼び出し、または PTHREAD_MUTEX_INITIALIZER の割り当てという 2 通りの方法で初期化することができます。

条件変数 は、スレッドによって使用され、特定のイベントの発生を待ちます。このようなイベントを検出したり引き起こしたりするスレッドには、 signal または broadcast があり、これらは待ち状態の 1 つまたは複数のスレッドを発生させます。

読み込み/書き込みロック では、読み込み/書き込みロックによって保護されている構造への複数のスレッドによる並列読み込みアクセスが許可されますが、書き込みアクセスを許可されるスレッドは 1 つだけです。

pthread_mutex_init(),
pthread_mutex_destroy()

  • mutex ロックの内容を初期化/消去します。

pthread_mutex_lock(),
pthread_mutex_trylock(),
pthread_mutex_unlock()

  • mutex をロック/ロック解除します。

pthread_mutex_getprioceiling(),
pthread_mutex_setprioceiling()

  • mutex ロックの優先順位を操作します。

pthread_mutexattr_init(),
pthread_mutexattr_destroy(),
pthread_mutexattr_getprioceiling(),
pthread_mutexattr_getprotocol(),
pthread_mutexattr_getpshared(),
pthread_mutexattr_gettype(),
pthread_mutexattr_getspin_np(),
pthread_mutexattr_setprioceiling(),
pthread_mutexattr_setprotocol(),
pthread_mutexattr_setpshared(),
pthread_mutexattr_settype(),
pthread_mutexattr_setspin_np()

  • pthread_mutex_init() に使用される mutex 属性を管理します。 既存の mutex に対して変更できるのは、"prioceiling" 属性だけです。

pthread_mutex_getyieldfreq_np(),
pthread_mutex_setyieldfreq_np()

  • これらの関数は、 spin 属性とともに使用され、mutex パフォーマンスを特定のアプリケーションに調整します。

pthread_cond_init(),
pthread_cond_destroy()

  • 読み込み/書き込みロックの内容を初期化/消去します。

pthread_cond_signal(),
pthread_cond_broadcast(),
pthread_cond_timedwait(),
pthread_cond_wait()

  • 条件変数を待機するか、またはその発生を合図します。

pthread_condattr_init(),
pthread_condattr_destroy(),
pthread_condattr_getpshared(),
pthread_condattr_setpshared()

  • pthread_cond_init() に使用される条件変数属性を管理します。

pthread_rwlock_init(),
pthread_rwlock_destroy()

  • 読み込み/書き込みロック内容を初期化/消去します。

pthread_rwlock_rdlock(),
pthread_rwlock_tryrdlock(),
pthread_rwlock_wrlock(),
pthread_rwlock_trywrlock(),
pthread_rwlock_unlock()

  • 読み込み/書き込みロックをロック/ロック解除します。

pthread_rwlockattr_init(),
pthread_rwlockattr_destroy(),
pthread_rwlockattr_getpshared(),
pthread_rwlockattr_setpshared()

  • pthread_rwlock_init() に使用される読み込み/書き込みロック属性を管理します。

POSIX 1.b のセマフォ

POSIX 1.b 規格で指定されるセマフォ関数も、マルチスレッドのアプリケーションでの同期化のために使用することができます。

sem_init(),
sem_destroy()

  • セマフォの内容を初期化/消去します。

sem_post(),
sem_wait(),
sem_trywait()

  • セマフォ値 (ブロック化が可能 possibly blocking) を増加/減少させます。

シグナル

マルチスレッド処理では、すべてのスレッドは、シグナル動作を共有します。つまり、あるスレッドによって設定されたシグナルハンドラーがすべてのスレッドによって使用されます。 ただし、各スレッドに個別のシグナルマスクがあり、これによってスレッドは選択的にシグナルをブロックすることができます。

同じプロセス内の他のスレッドまたは他のプロセスにシグナルを送ることができます。シグナルがプロセスに送られると、そのシグナルをブロックしていないスレッドの 1 つが処理を行います。同じプロセス内のスレッドにシグナルが送られると、おそらく後でそのシグナルがブロックされる場合でも、そのスレッドがそのシグナルを処理します。終了、停止、または続行の動作を指すシグナルは、特定のスレッドで指示された場合でも、それぞれ、プロセス全体を終了、停止、または続行します。

pthread_kill() 

指定したスレッドにシグナルを送ります。

pthread_sigmask()
  

スレッドに対して選択したシグナルをブロックします。

sigwait(),
sigwaitinfo(),
sigtimedwait()

  • これらの関数は、指定したシグナルを同期的に待ちます。

スレッド固有データ

スレッド固有データ (TSD) は、スレッドに専用の、つまり固有のグローバルデータです。各スレッドは、同じスレッド固有データ変数に対して異なる値を持ちます。グローバルな errno はスレッド固有のグルーバルデータの典型的な例です。

各スレッド固有のデータ項目は、キーに関連付けられています。このキーは、すべてのスレッドによって共有されます。ただし、スレッドがこのキーを参照する場合は、データの独自の専用コピーを参照します。

pthread_key_create(),
pthread_key_destroy()

  • これらの関数は、スレッド固有データのキーを管理します。

pthread_getspecific(),
pthread_setspecific()

  • これらの関数は、キーに関連付けられているデータ値の検索および割り当てを行います。

HP-UX コンパイラは、 スレッドローカル記憶領域 (TLS) という記憶領域のクラスをサポートします。(これは、POSIX の標準的な機能ではありません。) TLS は、値の作成/設定/取得のために関数が必要でないこと以外は、TSD と同じです。TLS 変数は、通常のグローバル変数とまったく同様にアクセスされます。TLS 変数は、次の構文を使用して宣言することができます。

 __thread     int     zyx;

キーワード __thread は、 zyx が TLS 変数であることをコンパイラに指示します。現在、各スレッド次のような文によって TLS を設定または取得することができます。

zyx = 21;

各スレッドは、 zyx に異なる値を関連付けます。

TLS 変数は静的に初期化することができます。 初期化されていない TLS 変数には 0 が設定されます。 動的にロードされるライブラリ (shl_load() を使用) は、TLS 変数を宣言して使用することができます。

スレッドが TLS 変数を使用するかどうかにかかわらず、各スレッドのための TLS スペースを割り当てて初期化しなければならないので、TLS では、スレッド作成/終了処理に負担がかかります。 これは、起動時に静的にリンクされるモジールにあてはまります。 (sh_load() によって) 動的にロードされるライブラリの場合、スレッドの TLS スペースは、スレッドが TLS 変数にアクセスしたときに割り当てられます。 大きな TLS 領域を実際に使うスレッドがほとんどない場合は、代わりに POSIX TSD (上記) を使用することをお勧めします。

再入可能な LIBC および STDIO

これらは、ライブラリ内部の静的データを指すポンイタを返すので、マルチスレッドのプログラム内では多数の libc を使用することはできません。この理由は、スレッド内のこれらの関数の呼び出しによって他のスレッド内での以前の呼び出しの結果が上書きされるからです。 スレッドプログラムの作成のためには、 接尾辞 _r (再入可能を表す) が付いた代わりの関数が libc 内に用意されています。

さらに、標準的な I/O 動作の同期化のために、いくつかの基本関数が用意されています。

asctime_r(),
ctime_r(),
getgrgid_t(),
getgrnam_r(),
getlogin_r(),
getpwnam_r(),
getpwuid_r(),
gmtime_t(),
localtime_r(),
rand_r(),
readdir_r(),
strtok_r(),
ttyname_r()

  • 既存の libc 関数の再入可能バージョンです。

flockfile(),
ftrylockfile(),
funlock()

  • 標準的な I/O ストリームに対して明示的な同期化を行います。

その他の関数

この項では、これまでに説明していないその他の pthread に関連する関数の概要を示します。

pthread_atfork() 

fork() 処理の直前および直後に呼びだす特殊関数を設定します。

pthread_equal() 

2 つの pthread_t 値が同じ pthread を表しているかどうかを調べます。

pthread_once() 

いくつのスレッドが同じ呼び出しを行っているかにかかわらず、プロセス内で指定した関数を 1 度だけ実行します (1 回限りのデータの初期化に有効です)。

pthread_self() 

呼び出しを行っているスレッドの識別子 (pthread_t) を返します。

スレッドのデバッグ

マルチスレッドのプログラムのデバッグは、標準的な HP-UX デバッガ dde でサポートされています。 デバッガイベントによってあるスレッドが停止すると、デバッガはすべてのスレッドを停止します。任意のスレッドのレジスタの状態、スタック、およびデータを調べて操作することができます。

詳細については、 dde(1) マンページおよび組み込みのグラフィック ヘルプシステムを参照してください。

トレース機能

HP-UX では、pthread の処理のためにトレース機能を用意しています。これを使用するためには、次のようにして、トレースバージョンのライブラリを使用してアプリケーションをリンクしなければなりません。

cc -D_POSIX_C_SOURCE=199506L -o myapp myapp.c -lpthread_tr -lcl

アプリケーションは、実行されると、pthread イベントに関するスレッド単位のファイルを作成します。これは、 『HP/PAK パフォーマンス アプリケーションキット』 内で使用可能な ttv スレッドトレース表示機能への入力として使用されます。

トレースデータ ファイルを制御するために、下記の環境変数が定義されています。

THR_TRACE_DIR 

トレースデータ ファイルを入れる場所です。これが定義されていない場合、このファイルは現在のワークディレクトリに入ります。

THR_TRACE_ASYNC 

デフォルトによって、トレースレコードはバッファーに入れられ、バッファーが一杯になったときにだけファイルに書き込まれます。この変数に NULL でない値が設定されていると、データはただちにトレースファイルに書き込まれます。

THR_TRACE_EVENTS 

デフォルトによって、すべての pthread イベントがトレースされます。この変数が定義されていると、定義されいてるカテゴリだけがトレースされます。各カテゴリは ':' で分割されます。 可能性のあるカテゴリとして、以下のものがあります。

thread:cond:mutex:rwlock

たとえば、スレッドおよび mutex の処理だけをトレースするには、 THR_TRACE_EVENTS 変数を次のように設定します。

thread:mutex

トレースファイルのレコードフォーマットの詳細説明は、 /usr/include/sys/trace_thread.h にあります。

トレース情報の使用に関する詳細については、 ttv(1) マンページおよび組み込みのグラフィック ヘルプシステムを参照してください。

パフォーマンスに関する考察

シングルスレッドよりもパフォーマンスを向上させるために、アプリケーションをマルチスレッドにするように設計する場合が多くあります。ただし、マルチスレットアプローチでは、シングルスレッドの場合にはほとんど関係のない問題に注意が必要です。これらは、従来からマルチプロセッサシステムのプログラミングに関連する問題です。

この設計には、データ構造およびアクセスパターンに適した大きさのデータ に分けてロックしなければなりません。 比較的大量の データに分けてロックし、保護する場合、不必要なロックの競合 を引き起こし、アプリケーションの並列処理能力を減少させることがあります。 他方、 非常に少量の データに分けてロックし、保護する場合、ロック動作が多きくなり、プロセッサが無駄な処理を行わなければならなくなる可能性があります。

スレッド固有データ (TSD) を使用すること、およびスレッドローカル 記憶領域 (TLS) を使用することは、上で説明したように (スレッド固有データ を参照)、トレードオフになります。

Mutex の spin および yield frequency 属性を使用すると、アプリケーションへの mutex の動作を調整することができます。 詳細については、 pthread_mutexattr_setspin_np(3T) および pthread_mutex_setyieldfreq_np(3T) を参照してください。

default stacksize 属性を設定すると、システムスレッドのキャッシュ動作を向上させることができます。 詳細については、 pthread_default_stacksize_np(3T) を参照してください。

複数のスレッドは、実際には同時に実行しているので、複数のプロセッサから同じデータをアクセスしている可能性があります。 ハードウェアプロセッサがそれぞれのデータのキャッシュを調整するので、プロセッサが古いデータ を使用することはありません。 あるプロセッサがデータをアクセス (特に書き込み処理のために) する場合、他のプロセッサはそれぞれのキャッシュから古いデータを初期化しなければなりません。 複数のプロセッサが同一のデータの読み込み/書き込みを繰り返す場合、命令ストリームの実行を低速にするキャッシュスラッシング を引き起こす可能性があります。これは、複数のスレッドが同じハードウェアのキャッシュ可能な単位 (キャッシュライン と呼ばれる) にある別々のデータ項目をアクセスする場合にも発生することがあります。 後者の状況をフォールスシェアリング と呼びますが、これは、データの間隔を開けてこのような一般的な項目を互いに近くに保存しないようにすることによって、避けることができます。

用語集

以下の用語の定義は、Scott J. Norton、Mark D. DiPasquale 共著によるテキスト「ThreadTime\c 」(Prentice-Hall、ISBN 0-13-190067-6、1996 年発行) から抽出したものです。

アプリケーション プログラミング インタフェース (API)

インタフェースは、エンティティへのアクセスまたはエンティティ間の通信を行なう伝達手段です。プログラミングの世界では、インタフェースは、関数とのアクセス (または通信) がどのように行なわれるかを記述します。特に、パラメータの数、名前、および目的は、関数へのアクセス方法を表します。API は、関数へのアクセスを行なう機能です。

非同期キャンセルセーフ

キャンセル状態が PTHREAD_CANCEL_ENABLE に設定され、キャンセルタイプが PTHREAD_CANCEL_ASYNCHRONOUS に設定されているスレッドから呼び出すことができる関数です。 このような関数の中の 1 つでスレッドがキャンセルされた場合、その関数内に状態は残りません。これらの関数は、通常、その関数のタスクを実行するために資源を獲得することはありません。

非同期シグナルセーフ

非同期シグナルセーフの関数は、シグナルハンドラーによって呼び出すことができる関数です。シグナルハンドラーによって安全に呼び出すことができる関数は、一連の限定された関数だけです。これらの関数のリストは、POSIX.1c 規格の 3.3.1.3 項に記載されています。

非同期シグナル

非同期シグナルは、外部イベントにより生成されるシグナルです。 kill() により送信されるシグナルおよびタイマーの満了または非同期 I/O の完了によって生成されるシグナルは、すべて非同期に生成されるシグナルの例です。非同期シグナルは、プロセスに配信されます。シグナルは、すべて非同期に生成される可能性があります。

fork 時ハンドラー

アプリケーションにより提供および登録され、 fork() 処理の前後に呼び出される関数です。これらの関数は、通常の場合、fork() の前にすべての mutex ロックを獲得し、fork() の後に親プロセスおよび子プロセスの両方でそれらの mutex ロックを解除します。

最小単位での操作

2 つの命令であるかのように完了することが保証される操作、つまり一連のイベント。

バリヤ関数

アプリケーション内の指定した点で一定の数のスレッドを待たせる、つまり集める同期的基本関数。バリヤ関数は、次の作業に進む前にすべてのスレッドがなんらかの操作を完了していることをアプリケーションが保証する必要のある場合に使用されます。

バインドされたスレッド

カーネルでスケジューリングされるエンティティに直接バインドされているユーザースレッド。このようなスレッドは、システムのスケジューリング範囲を含んでいるので、直接カーネルによってスケジューリングされます。

キャッシュスラッシング

キャッシュスラッシングは、1 つのスレッドが異なるプロセッサ上で実行している状況です。キャッシュされたデータを異なるプロセッサのキャッシュへ、またはキャッシュから移動させます。キャッシュスラッシングにより、重大なパフォーマンスの低下が引き起こされる可能性があります。

キャンセルクリーンアップ ハンドラー

アプリケーションにより提供および登録され、スレッドがキャンセルされる際に呼び出される関数です。これらの関数は、通常の場合、スレッドのキャンセル中に、スレッドのクリーンアップ処理を実行します。これらのハンドラーは、シグナルハンドラーに似ています。

条件変数

条件変数は、スレッドがイベントを待つことができるようにするために使用される同期的基本関数です。条件変数は、作成側のスレッドが 1 つまたは複数の消費側のスレッドに何かを提供しなければならない、作成側と消費側のスレッド間の問題の中で使用されることが多くあります。

コンテキストの切り替え

現在実行中のスレッドをプロセッサから削除し別のスレッドを実行する処理。コンテキストの切り替えでは、現在実行中のスレッドのレジスタの状態を保存して、次の実行のために選択されたスレッドのレジスタの状態を復元します。

クリティカルセクション

最小単位で割り込みなしに完了しなければならないコードのセクションです。コードのクリティカルセクションは、通常の場合、グローバルな資源 (変数、データ構造、リンクされたリストなど) が変更されるセクションです。実行中の操作は、他のスレッドが矛盾した状態でクリティカルセクションを参照しないように、最小単位で完了しなければなりません。

デッドロック

デッドロックは、1 つまたは複数のスレッドが実行できなくなったときに発生します。たとえば、スレッド A がロック 1 を設定し、ロック 2 でブロックされているとします。一方、スレッド B がロック 2 を設定し、ロック 1 でブロックされているとします。すると、スレッド A および B は、永久にデッドロック状態になります。デッドロックは、スレッドを持つ任意の数の資源で発生する可能性があります。 相互デッドロック は、2 つ以上のスレッドが関係します。 再帰 (または 自己) デッドロック は 1 つのスレッドだけが関係します。

アタッチ解除されたスレッド

スレッドの終了時にシステムにより自動的に解放される資源を持つスレッド。アタッチ解除されたスレッドは別のスレッドによって結合することはできません。つまり、アタッチ解除されたスレッドは、終了状態を返すことはできません。

結合可能なスレッド

別のスレッドが終了を待つことができるスレッド。結合可能なスレッドは、結合を行なうスレッドに終了状態を返すことができます。結合可能なスレッドは、終了後に別のスレッドによって結合されるまで、その状態を保持します。

カーネルモード

すべての操作が許可される操作モード。スレッドは、システムコールの実行中は、カーネルモードで実行しています。

カーネル空間

カーネルプログラムは、この空間に存在します。カーネルコードは、この空間の中で最高の権限レベルで実行されます。通常の場合、権限レベルには、ユーザーコード用のレベル (ユーザーモード) とカーネルコード用のレベル (カーネルモード) の 2 つがあります。

カーネルスタック

スレッドは、システムコールを行なう場合は、カーネルモードで実行します。カーネルモードの間、スレッドは、アプリケーションによって割り当てられたスタックを使用しません。代わりに、システムコール中は、別のカーネルスタックが使用されます。カーネルがスケジューリングするそれぞれのエンティティには、それがプロセス、カーネルスレッド、または軽量プロセスのどれでも、カーネルスタックが含まれます。スタックの一般的な説明については、スタック を参照してください。

カーネルスレッド

カーネルスレッドは、スレッドライブラリ内にあるスレッド関数によって作成されます。カーネルスレッドは、オペレーティングシステム カーネルから見ることができる カーネルがスケジューリングするエンティティ です。カーネルスレッドは、通常の場合、1 つまたは複数のユーザースレッドをサポートします。カーネルスレッドは、ユーザースレッドに代って、カーネルコードまたはシステムコールを実行します。一部のシステムでは、カーネルスレッドを 軽量プロセス と呼ぶ場合があります。 スレッドの一般的な説明については、 スレッド を参照してください。

軽量プロセス

カーネルがスケジューリングするエンティティ。一部のシステムでは、軽量プロセスをカーネルスレッドと呼ぶ場合があります。それぞれのプロセスには、1 つまたは複数の軽量プロセスが含まれます。1 つのプロセスの中にいくつの軽量プロセスが含まれるかは、そのプロセスがマルチスレッドプロセスであるかどうかおよびその程度によって決まります。スレッドの一般的な説明については、 スレッド を参照してください。

マルチプロセッサ

2 つ以上のプロセッサ (CPU) を持つシステム。マルチプロセッサでは、マルチスレッドアプリケーションが真の並列処理を行うことができます。

マルチスレッド

アプリケーションに複数の実行スレッドを持つことを可能にするプログラミングモード。マルチスレッドにより、アプリケーションは (マルチプロセッサシステム上で) 同時並列処理を行なうことができます。

Mutex

mutex は、相互排他同期的基本関数です。Mutex は、共有されるデータおよび資源へのアクセスを管理、または順番に実行する機能をスレッドに与えます。あるスレッドが mutex ロックを行なっている場合、このスレッドが mutex をロック解除するまで、mutex ロックを行なおうとしている他のスレッドはブロックされます。

POSIX

移植可能なオペレーティングシステム インタフェース。POSIX は、アプリケーションを移植できるようにするために複数のベンダーが従う一連の規格を定義します。Pthreads の規格 (POSIX 1003.1c) は、アプリケーション開発担当者に一連の移植可能なマルチスレッド用 API を提供します。

優先順位の逆転

優先順位の低いスレッドが優先順位の高いスレッドにより要求される資源を獲得している状況。この資源を獲得することができない場合、優先順位の高いスレッドはこの資源を待たなければなりません。最終的な結果として、優先順位の低いスレッドが優先順位の高いスレッドをブロックします。

プロセス

プロセスは、1 つまたは複数のスレッドのための、実行、アドレス空間、および共有プロセスの資源の入れ物と考えることができます。すべてのプロセスは最低でも 1 つのスレッドを持ちます。プロセス内の各スレッドはそのプロセスのアドレス空間内で実行します。プロセスが共有する資源の例としては、オープンファイル記述子、メッセージ待ち行列記述子、mutex、およびセマフォがあります。

プロセス制御ブロック (PCB)

この構造体には、プロセスのレジスタコンテキストが保存されます。

プロセス構造体

オペレーティングシステムは、システム内のそれぞれのプロセスごとにプロセス構造体を持っています。この構造体は、システム内で内部的に実在するプロセスを表します。プロセス構造体情報のサンプルとしては、プロセス ID、プロセスのオープンファイルの集合、シグナルベクトルがあります。プロセス構造体およびその中に含まれる値は、プロセスのコンテキストの一部です。

プログラムカウンター (PC)

プログラムカウンターは、プロセスのレジスタコンテキストの一部です。これは、現在実行される命令のアドレスを保存します。

競合状態

ある操作を実行中の 2 つ以上のスレッドの結果が予測できないタイミング要因によって決まる場合を競合状態といいます。

読み込み/書き込みロック

読み込み/書き込みロックは、同期的基本関数です。読み込み/書き込みロックは、プロセスが共有するデータおよび資源へのアクセスを管理、または順番に実行する機能をスレッドに与えます。読み込み/書き込みロックでは、複数の読み込みスレッドが同時に読み込みロックを獲得できるのに対して、同時に書き込みロックを獲得できる書き込みスレッドは 1 つだけです。これらのロックは、書き込みがまれにしか行われす、たいていは読み込みが行われる共有データに有効です。

再入可能関数

再入可能関数は、複数のスレッドによって呼び出され、それぞれのスレッドによって 1 つずつ順番に呼び出されたかのように動作する関数です。これらの関数は並列に実行する場合もあります。

スケジューリングの割り当てドメイン

1 つのスレッドがスケジューリングされているプロセッサの集合。このドメインのサイズは、いつでも動的に変更することができます。スレッドをあるドメインから別のドメインに移動することもできます。

スケジューリングの競合範囲

スケジューリングの競合範囲は、あるスレッドが資源のアクセスを競合するスレッドのグループを定義します。非常に多くの場合、競合範囲はプロセッサへのアクセスに該当します。ただし、この範囲は、複数のスレッドが他の資源を競合する場合にも使用することができます。システム範囲のスレッドは、そのシステム内の他のすべてのスレッドと資源へのアクセスを競合します。プロセス範囲のスレッドは、そのプロセス内の他のプロセス範囲のスレッドと資源へのアクセスを競合します。

スケジューリング方針

スケジューリング方針は、複数のスレッドを実行するために、いつ、どのようにスケジューリングするかを決定するために使用される一連の規則です。スケジューリング方針は、どれだけ長くスレッドに実行を許可するかについても決定します。

スケジューリングの優先順位

スケジューリングの優先順位は、一部のスケジューリング方針でスレッドに割り当てられる数値による優先順位の値です。優先順位の高いスレッドには、スケジューリングの決定を行う際に優先権が与えられます。

セマフォ

セマフォは mutex に似ています。セマフォは、1 つまたは複数の共有オブジェクトへのアクセスを管理します。セマフォには値が割り当てられます。この値は、通常の場合、そのセマフォによって管理される共有資源の数に設定されます。セマフォの値が 1 の場合には、バイナリセマフォです。基本的に、mutex はバイナリセマフォです。セマフォの値が 1 よりも大きい場合、 カウンティングセマフォ と呼ばれます。 カウンティングセマフォは、複数のスレッドによって同時にロックされる可能性があります。セマフォがロックされるたびに、この値は 1 つずつ減少していきます。この値がゼロになった後、そのセマフォを新たにロックしようとすると、そのセマフォが別のスレッドによってロック解除されるまで、ロックを行なおうとしているスレッドはブロックされます。

共有オブジェクト

共有オブジェクトは、プロセスのアドレス空間に存在し、そのプロセス内のすべてのスレッドによってアクセス可能な実体のあるエンティティです。マルチスレッドプログラミングの場合、「共有オブジェクト」はグローバル変数、ファイル記述子、および、スレッドによるアクセスを同期させることを要求する他のオブジェクトです。

シグナル

シグナルは、プロセスまたはスレッドにイベントを通知できるようにする簡略化された IPC 制御です。シグナルは、同期的、または非同期に生成することができます。

シグナルマスク

シグナルマスクは、スレッドがどのシグナルを受け入れ、どのシグナルが配信からブロックされるかを決定します。同期シグナルは、配信からブロックされた場合、そのスレッドがそのシグナルのブロックを解除するかまたはそのスレッドが終了するまで、保留されたままです。プロセスに配信される非同期シグナルがあるスレッドによって配信からブロックされている場合、プロセス内でこのシグナルをブロックしていない別のスレッドがこのシグナルを処理することができます。

シグナルベクトル

シグナルベクトルは、各プロセス内に含まれるテーブルで、それぞれのプロセス内のスレッドにシグナルが配信されたときに実行する動作を表します。それぞれのシグナルは、そのシグナルを無視する、シグナル処理関数を実行する、そのシグナルのデフォルトの動作 (通常は、プロセスの終了) を実行する、という 3 つの可能性のある動作の中の 1 つの動作を行ないます。

シングルスレッド

プログラムコードを通る 制御の流れ が 1 つだけ存在する (1 スレッド) ことを意味します。つまり、同時に実行される命令は 1 つだけです。

Spinlock

mutex に似た同期的基本関数。mutex ロックを獲得できない場合、そのロックを獲得したいスレッドは、ブロックされる代わりに、そのロックを獲得できるまでループ内を回ります。Spinlock は不適切に使用されやすく、これをシングルプロセッサシステムで使用すると、パフォーマンスが著しく低下する可能性があります。

疑似起動

スレッドを間違ってブロック解除すると、そのスレッドが待っていたイベントが発生しない場合でも、疑似起動が発生します。ブロックされているスレッドが通常のシグナルを受け取ったために、条件待ちが割り込みされて戻るのは、疑似起動の例です。

スタック

スタックは、スレッドによって、関数呼び出しの実行 (およびこれらの呼び出しからの復帰)、関数呼び出しへの引き数の引き渡し、および、関数呼び出し時に呼び出された関数内でのローカル変数への空間の割り当てを行なうために使用されます。バインドされたスレッドには、ユーザースタックとカーネルスタックがあります。バインドされていないスレッドにはユーザースタックだけがあります。

同期シグナル

同期シグナルは、特定のスレッドのある動作によって生成されるシグナルです。 たとえば、あるスレッドがゼロによる除算を行なったり、浮動小数点例外を引き起こしたり、不当な命令を実行したりすると、シグナルが同期的に生成されます。同期シグナルは、そのシグナルを送信させたスレッドに配信されます。

従来のプロセス

これは、1 つのプロセッサ上で実行をスケジューリングできるシングルスレッドエンティティです。

スレッド

スレッドは、プロセス内の独立した制御の流れであり、コンテキスト (レジスタセットおよびプログラムカウンターを含む) および一連の実行命令で構成されます

スレッドローカル記憶領域 (TLS)

スレッドローカル記憶領域は、基本的には、コンパイラからのサポートを要求するスレッド固有データです。TLS によって、アプリケーションは、スレッド固有のデータキーを使用するのではなく、実際のデータをスレッド固有のデータとして割り当てることができます。さらに、TLS では、スレッド固有データを取得するためにスレッドが関数呼び出しを行う必要はありません。スレッドは、このデータを直接アクセスすることができます。

スレッドセーフの関数

スレッドセーフの関数は、複数のスレッドによって同時に安全に呼び出すことができる関数です。この関数が共有データまたは資源をアクセスする場合、そのアクセスは mutex または何か別の形式の同期制御によって管理されます。

スレッド固有データ (TSD)

スレッド固有データは、スレッドに固有のグローバルデータです。すべてのスレッドは、同じデータ変数をアクセスします。ただし、各スレッドは、この変数に対してスレッド独自の値を持ちます。errno は、スレッド固有データの例です。

スレッド構造体

オペレーティングシステムは、システム内のそれぞれのスレッドごとにスレッド構造体を持っています。この構造体は、システム内で内部的に実在するスレッドを表します。スレッド構造体情報のサンプルとして、スレッド ID、スケジューリング方針および優先順位、シグナルマスクがあります。スレッド構造体およびその中に含まれる値は、スレッドのコンテキストの一部です。

ユーザーモード

操作のサブセットが許可される操作モード。スレッドは、アプリケーションコードの実行中は、ユーザーモードで実行しています。スレッドは、システムコールを行なう場合には、モードを変更して、そのシステムコールが完了するまでカーネルモードで実行します。

ユーザー空間

ユーザーコードは、この空間に存在します。ユーザーコードは、この空間の中で通常の権限レベルで実行されます。通常の場合、権限レベルには、ユーザーコード用のレベル (ユーザーモード) とカーネルコード用のレベル (カーネルモード) の 2 つがあります。

ユーザースタック

スレッドは、ユーザー空間の中でコードを実行している間、関数呼び出しの実行、パラメータの引き渡し、およびローカル変数を作成のためにスタックを使用する必要があります。ユーザーモードでは、スレッドはカーネルスタックを使用しません。代わりに、それぞれのユーザースレッドによって別々のユーザースタックが使用するために割り当てられます。スタックの一般的な説明については、 スタック を参照してください。

ユーザースレッド

pthread_create() が呼び出されると、ユーザースレッドが作成されます。カーネルがスケジューリングするエンティティ (カーネルスレッドまたは軽量プロセス) も作成されるかどうかは、そのユーザースレッドのスケジューリングの競合範囲によって決まります。バインドされたスレッドが作成されると、ユーザースレッドとカーネルがスケジューリングするエンティティの両方が作成されます。バインドされていないスレッドが作成されると、通常の場合、ユーザースレッドだけが作成されます。スレッドの一般的な説明については、 スレッド を参照してください。

参照

thread_safety(5)

Scott J. Norton、Mark D. DiPasquale 共著 『ThreadTime』 (Prentice-Hall、ISBN 0-13-190067-6、1996 年発行)

印刷用画面へ
プライバシー 本サイト利用時の合意事項
© 1983-2004 Hewlett-Packard Development Company, L.P.