はじめに
この連載ではUNIX系OSなどで使われるスレッド「pthread」についてサンプルを交えて説明していきます。pthreadはPOSIXが仕様化したスレッドモデルです。サンプルはCと一部C++、調査環境はFedora 8(2.6.23.1-49.fc8)、32bit、glibc-4.1-2、gcc-4.1.2-33およびFedora Core 6(2.6.18-1.2798.fc6)、32bit、glibc-2.5-3、gcc-4.1.1-30を使用しています。
前回の記事
- 第1回:pthreadについて(概要・生成)
- 第2回:pthreadについて(同期)
- 第3回:pthreadについて(条件変数・モデル)
- 第4回:pthreadについて(スレッド固有データ)
- 第5回:pthreadについて(スタックサイズ)
9. スケジューリング(リファレンス)
LinuxやWindowsに代表されるOSは、複数の実行可能状態のスレッドやプロセスに対し、何らかの基準で実行すべき対象を選び、プロセスおよびスレッドを実行しています。いわゆるスケジューリングと言われている機能ですが、スレッドやプロセスはOSに対して明示的にスケジューリングを依頼するためのインターフェースを備えています。そのインターフェースを使用する事で、一部のスレッドに対して他スレッドと比べて優先的に処理を行うよう指示することができ、逆に全スレッドに対して平等に動作させる事もできます。
しかしOSの仕事に対して明示的に指示する機能なので一部例外もあるものの、、当機能は特権を持つユーザーにのみ使用が許可されています。また、初期のLinuxカーネルにはスケジューリングがちゃんとサポートされていなかったようです。
下記マクロを参照する事で自環境にスケジューリングがサポートされているか確認できます。
マクロ | 動作 |
_POSIX_PRIORITY_SCHEDULING | プロセスに対しスケジューリングが可能か |
_POSIX_THREAD_PRIORITY_SCHEDULING | スレッドに対しスケジューリングが可能か |
_POSIX_THREAD_PRIO_PROTECT | プライオリティ最高限度mutexが利用可能か |
_POSIX_THREAD_PRIO_INHERIT | プライオリティ継承mutexが利用可能か |
#include <stdio.h> #include <unistd.h> #ifdef _POSIX_PRIORITY_SCHEDULING #error "_POSIX_PRIORITY_SCHEDULING defined" #else #error "_POSIX_PRIORITY_SCHEDULING not defined" #endif #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING #error "_POSIX_THREAD_PRIORITY_SCHEDULING defined" #else #error "_POSIX_THREAD_PRIORITY_SCHEDULING not defined" #endif #ifdef _POSIX_THREAD_PRIO_PROTECT #error "_POSIX_THREAD_PRIO_PROTECT defined" #else #error "_POSIX_THREAD_PRIO_PROTECT not defined" #endif #ifdef _POSIX_THREAD_PRIO_INHERIT #error "_POSIX_THREAD_PRIO_INHERIT defined" #else #error "_POSIX_THREAD_PRIO_INHERIT not defined" #endif
スレッドの場合、スケジューリングを行うにはスレッドを生成する際に属性を付加する事で対応できます。スレッド属性およびその初期化方法については8章を参照してください。
スケジューリングはプライオリティおよびポリシーで決定されます。まずは関数リファレンスを、それ以降でプライオリティやポリシーの詳細を述べていきます。
9.1 リファレンス
主にスレッド属性の設定にかかわる関数は下記の通りです。より詳細についてはman
コマンドを参照してください。
- int pthread_attr_getschedparam( const pthread_attr_t * attr, struct sched_param * param );
pthread_attr_getschedparam
:現在設定されているスケジューリングパラメータを取得できます。pthread_attr_t
:初期化済みのスレッド属性オブジェクト。struct sched_param * param
:スケジューリング用のパラメータを取得する領域。構造体ですが、私の環境ではメンバは int sched_priorityのみです。
- int pthread_attr_setschedparam( pthread_attr_t *attr, const struct sched_param *param);
pthread_attr_setschedparam
:スケジューリングパラメータを設定します。
- int sched_get_priority_max(int policy);
sched_get_priority_max
:ポリシーにおける最大プライオリティを取得します。
- int sched_get_priority_min(int policy);
sched_get_priority_min
:ポリシーにおける最小プライオリティを取得します。
- int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
pthread_attr_setschedpolicy
:新しいポリシーを設定します。policy
:SCHED_FIFO / SCHED_RR / SCHED_OTHERのみ取ります。
- int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
pthread_attr_getschedpolicy
:現時点でのポリシーを取得します。
- int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit);
pthread_attr_setinheritsched
:親プロセスのスケジューリングパラメータを引き継ぐか、新規で競っているかinherit
:親スレッドおよび親プロセスのスケジューリングパラメータを継承するか新規で割り付けるかを指定します。PTHREAD_INHERIT_SCHED / PTHREAD_EXPLICIT_SCHEDのみ取ります。