プログラミングインタフェース

第 4 章 プロセススケジューラ

この章では、プロセスのスケジューリングとスケジューリングの変更方法について説明します。

この章は、プロセスの実行順序についてデフォルトのスケジューリングが提供する以上の制御を行う必要がある開発者を対象としています。マルチスレッド化されたスケジューリングについては、『マルチスレッドのプログラミング』を参照してください。

スケジューラの概要

生成されたプロセスには 1 つの軽量プロセス (LWP) がシステムによって割り当てられます。プロセスがマルチスレッド化されている場合、複数の LWP がそのプロセスに割り当てられる可能性もあります。LWP とは、UNIX システムスケジューラによってスケジューリングされ、プロセスをいつ実行するかを決定するオブジェクトのことです。スケジューラは、構成パラメータ、プロセスの動作、およびユーザーの要求に基づいてプロセスの優先順位を管理します。スケジューラはこれらの優先順位を使用して、次に実行するプロセスを判断します。優先順位には、リアルタイム、システム、対話型(IA)、固定優先順位(FX)、公平共有(FSS)、およびタイムシェアリング(TS) の 6 つのクラスがあります。

デフォルトでは、タイムシェアリング方式を使用します。この方式は、プロセスの優先順位を動的に調整して、対話型プロセスの応答時間を調節します。この方式はまた、プロセスの優先順位を動的に調整して、CPU 時間を多く使用するプロセスのスループットを調整します。タイムシェアリングは優先順位がもっとも低いスケジューリングクラスです。

SunOS 5.10 のスケジューラでは、リアルタイムスケジューリング方式も使用できます。リアルタイムスケジューリングによって、ユーザーは特定のプロセスに固定優先順位を割り当てることができます。リアルタイムスケジューリングのユーザープロセスは優先順位がもっとも高く、プロセスが実行可能になり次第 CPU を取得できます。

SunOS 5.10 スケジューラでは、固定優先順位スケジューリング方式も使用できます。固定優先順位スケジューリングによって、ユーザーは特定のプロセスに固定優先順位を割り当てることができます。デフォルトでは、固定優先順位スケジューリング方式はタイムシェアリングスケジューリングクラスと同じ優先順位の範囲を使用します。

リアルタイムプロセスがシステムからの応答時間を保証されるように、プログラムを作成できます。詳細は、第 12 章リアルタイムプログラミングと管理を参照してください。

リアルタイムスケジューリングによるプロセススケジューリングを制御する必要はほとんどありません。ただし、プログラムの要件に厳しいタイミングの制約が含まれるときは、リアルタイムプロセスがそれらの制約を満たす唯一の方法となることがあります。


注意 – 注意 –

リアルタイムプロセスを不用意に使用すると、タイムシェアリングプロセスの性能が極めて悪くなることがあります。


スケジューラ管理を変更すると、スケジューラの動作に影響する可能性があるため、プログラマもスケジューラ管理について多少理解しておく必要があります。スケジューラ管理に影響を与えるインタフェースは次のとおりです。

作成されたプロセスは、そのクラス内のスケジューリングクラスや優先順位を含むスケジューリングパラメータを継承します。ユーザーの要求によってのみプロセスのスケジューリングクラスが変更されます。システムは、ユーザーの要求とそのプロセスのスケジューリングクラスに関連する方針に基づいて、プロセスの優先順位を管理します。

デフォルトの設定では、初期化プロセスはタイムシェアリングクラスに属します。そのため、すべてのユーザーログインシェルは、タイムシェアリングプロセスとして開始します。

スケジューラは、クラス固有優先順位をグローバル優先順位に変換します。プロセスのグローバル優先順位は、プロセスをいつ実行するかを判断します。スケジューラは常に、グローバル優先順位がもっとも高い実行可能なプロセスを実行します。優先順位の高いプロセスが先に実行されます。CPU に割り当てられたプロセスは、プロセスが休眠するか、そのタイムスライスを使い切るか、または優先順位がさらに高いプロセスによって横取りされるまで実行されます。優先順位が同じプロセスは循環方式で順番に実行されます。

リアルタイムプロセスは、どのカーネルプロセスよりも優先順位が高く、カーネルプロセスは、どのタイムシェアリングプロセスよりも優先順位が高くなっています。


注 –

シングルプロセッサシステムにおいては、実行可能なリアルタイムプロセスが存在している間、カーネルプロセスやタイムシェアリングプロセスは実行されません。


管理者はデフォルトのタイムスライスを構成テーブルで指定します。ユーザーはプロセスごとのタイムスライスをリアルタイムプロセスに割り当てることができます。

プロセスのグローバル優先順位は、ps(1) コマンドの -cl オプションで表示できます。クラス固有の優先順位についての設定内容は、priocntl(1) コマンドと dispadmin(1M) コマンドで表示できます。

以降の節では、6 つのスケジューリングクラスのスケジューリング方式について説明します。

タイムシェアリングクラス (TS クラス)

タイムシェアリング方式の目的は、対話型プロセスには最適な応答性能を提供し、CPU 時間を多く使用するプロセスには最適なスループットを提供することです。スケジューラは、切り替えに時間がかかりすぎない頻度で CPU の割り当てを切り替え、応答性能を高めます。タイムスライスは通常、数百ミリ秒です。

タイムシェアリング方式では、優先順位が動的に変更され、異なる長さのタイムスライスが割り当てられます。CPU をほんの少しだけ使用したあとで休眠しているプロセスの優先順位はスケジューラによって上げられます。たとえば、あるプロセスは端末やディスクの読み取りなどの入出力操作を開始すると休眠します。頻繁に休眠するのは、編集や簡単なシェルコマンドの実行など、対話型タスクの特性です。一方、休眠せずに CPU を長時間使用するプロセスの優先順位は下げられます。

デフォルトのタイムシェアリング方式では、優先順位が低いプロセスに長いタイムスライスが与えられます。優先順位が低いプロセスは、CPU を長時間使用する傾向があるからです。ほかのプロセスが CPU を先に取得しても、優先順位の低いプロセスが CPU を取得すると、そのプロセスは長いタイムスライスを取得します。ただし、タイムスライス中に優先順位がより高いプロセスが実行可能になると、そのプロセスが CPU を横取りします。

グローバルプロセスの優先順位とユーザー指定の優先順位は、昇順になります。 優先順位の高いプロセスが先に実行されます。ユーザー指定の優先順位は、設定されている値の、負の最大値から正の最大値までの値になります。プロセスはユーザー指定の優先順位を継承します。ユーザー指定の優先順位のデフォルトの初期値は 0 です。

「ユーザー指定の優先順位限界」は、構成によって決まったユーザー指定の優先順位の最大値です。ユーザー指定の優先順位は、この限界値より低い任意の値に設定できます。適当なアクセス権を持っていると、ユーザー指定の優先順位限界を上げることができます。ユーザー優先順位限界のデフォルト値は 0 です。

プロセスのユーザー指定の優先順位を下げると、プロセスに与える CPU へのアクセス権を減らすことができます。あるいは、適当なアクセス権をもちいてユーザー指定の優先順位を上げるとサービスを受けやすくできます。ユーザー指定の優先順位はユーザー指定の優先順位限界より高くには設定できません。このどちらの値もデフォルト値の 0 である場合は、ユーザー指定の優先順位を上げる前に、ユーザー指定の優先順位限界を上げる必要があります。

管理者は、グローバルなタイムシェアリング優先順位とはまったく別にユーザー指定の優先順位の最大値を設定します。たとえば、デフォルトの設定では、ユーザーはユーザー指定の優先順位を –20 から +20 までの範囲で設定できます。しかし、タイムシェアリングのグローバル優先順位は 60 種類まで設定できます。

スケジューラは、タイムシェアリングのパラメータテーブル ts_dptbl(4) 内の設定可能なパラメータを使用して、タイムシェアリングプロセスを管理します。このテーブルには、タイムシェアリングクラス固有の情報が含まれます。

システムクラス

システムクラスでは、固定優先順位方式を使用して、サーバーなどのカーネルプロセスや、ページングデーモンなどのハウスキーピングプロセスを実行します。システムクラスはカーネルが使用するために予約されています。ユーザーはシステムクラスにプロセスを追加できません。ユーザーはまた、システムクラスからプロセスを削除できません。システムクラスのプロセスの優先順位はカーネルコードに設定されています。設定されたシステムプロセスの優先順位は変わりません。カーネルモードで動作しているユーザープロセスはシステムクラスではありません。

リアルタイムクラス

リアルタイムクラスでは、固定優先順位スケジューリング方式を使用しているため、クリティカルなプロセスがあらかじめ設定された順序で実行されます。リアルタイム優先順位は、ユーザーが変更しない限り変更されません。特権ユーザーは、priocntl(1) コマンドまたは priocntl(2) インタフェースを使用して、リアルタイム優先順位を割り当てることができます。

スケジューラは、リアルタイムパラメータテーブル rt_dptbl(4) 内の設定可能なパラメータを使用して、リアルタイムプロセスを管理します。このテーブルには、リアルタイムクラス固有の情報が含まれています。

対話型クラス (IA クラス)

IA クラスは TS クラスにとてもよく似ています。ウィンドウイングシステムと組み合わせて使用すると、プロセスの優先順位は入力フォーカスがあるウィンドウ内で動作している間だけより高くなります。システムがウィンドウイングシステムを実行している場合、デフォルトのクラスは IA クラスです。そうでない場合、IA クラスは TS クラスと同じであり、 2 つのクラスは同じ ts_dptbl ディスパッチパラメータテーブルを共有します。

公平共有クラス (FSS クラス)

FSS クラスは、Fair-Share Scheduler (FSS(7)) がアプリケーション性能を管理する (つまり、CPU 資源の共有をプロジェクトに明示的に割り当てる) ときに使用されます。共有は、プロジェクトが CPU 資源を利用できる権利を意味します。システムは資源の使用率を時間の経過とともに監視します。使用率が高い場合、システムは権利を減らします。使用率が低い場合、システムは権利を増やします。FSS は複数のプロセスに CPU 時間をスケジューリングするとき、各プロジェクトが所有するプロセスの数とは無関係に、プロセスの所有者の権利に従います。FSS クラスは、TS クラスおよび IA クラスと同じ優先順位の範囲を使用します。詳細は、FSS のマニュアルページを参照してください。

固定優先順位クラス(FX クラス)

FX クラスは、優先順位が固定された横取りのスケジューリング方式です。この方式は、ユーザーまたはアプリケーションがスケジューリング優先順位を制御する必要があるが、システムが動的に調節してはならないプロセス向けです。デフォルトでは、FX クラスは TS クラス、IA クラス、および FSS クラスと同じ優先順位の範囲を使用します。FX クラスを使用すると、ユーザーまたはアプリケーションはこのクラス内のプロセスに割り当てられたユーザー指定の優先順位値を使用して、スケジューリング優先順位を制御できます。このようなユーザー指定の優先順位値は、固定優先順位プロセスのスケジューリング優先順位をそのクラス内のほかのプロセスと相対的に決定します。

スケジューラは固定優先順位ディスパッチパラメータテーブル fx_dptbl(4) の構成可能なパラメータを使用して、固定優先順位プロセスを管理します。このテーブルには、固定優先順位クラス固有の情報が収められています。

コマンドとインタフェース

次の図に、デフォルトのプロセス優先順位を示します。

図 4–1 プロセス優先順位 (プログラマから見た場合)

リアルタイムスレッドの優先順位はシステムスレッドよりも高い。システムスレッドの優先順位はタイムシェアリングスレッドよりも高い。各クラスは個々の実行待ち行列を持ちます。

プロセス優先順位が意味を持つのは、スケジューリングクラスについてだけです。プロセス優先順位を指定するには、クラスとクラス固有の優先順位の値を指定します。クラスとクラス固有の値は、システムによってグローバル優先順位に割り当てられ、この値を使用してプロセスがスケジューリングされます。

優先順位は、システム管理者から見た場合とユーザーまたはプログラマから見た場合とで異なります。スケジューリングクラスを設定する場合、システム管理者はグローバル優先順位を直接取り扱います。システムでは、ユーザーが指定した優先順位は、このグローバル優先順位に割り当てられます。優先順位の詳細は、『Solaris のシステム管理 (基本編)』を参照してください。

ps(1) コマンドで -cel オプションを指定すると、動作中のすべてのプロセスのグローバル優先順位が表示されます。priocntl(1) コマンドを指定した場合、ユーザーとプログラマが使用するクラス固有の優先順位が表示されます。

priocntl(1) コマンド、priocntl(2) インタフェース、および priocntlset(2) インタフェースは、プロセスのスケジューリングパラメータを設定または取得するために使用されます。優先順位を設定するときには、これらのコマンドおよびインタフェースいずれの場合でも、次の同じ手順に従います。

  1. ターゲットプロセスを指定する。

  2. そのプロセスに希望するスケジューリングパラメータを指定する。

  3. プロセスにパラメータを設定するコマンドまたはインタフェースを実行する。

プロセス ID は UNIX プロセスの基本設定項目です。詳細は、Intro(2) を参照してください。クラス ID はプロセスのスケジューリングクラスです。priocntl(2) は、タイムシェアリングクラスと実時間クラスだけに有効で、システムクラスには使用できません。

priocntl の使用法

priocntl(1) ユーティリティーは、プロセスをスケジューリングする際に、次の 4 つの制御インタフェースを実行します。

priocntl -l

構成情報を表示します

priocntl -d

プロセスのスケジューリングパラメータを表示します

priocntl -s

プロセスのスケジューリングパラメータを設定します

priocntl -e

指定したスケジューリングパラメータでコマンドを実行します

次に、priocntl(1) を使用したいくつかの例を示します。

priocntl(1) には、nice(1) のインタフェースが含まれます。nice(1) は、タイムシェアリングプロセスについてだけ有効で、数値が大きいほど優先順位が低くなります。前述の例は、nice(1) を使用してインクリメントを 10 に設定するのと同じです。


$ nice -10 make bigprog

priocntl インタフェース

priocntl(2) は、1 つのプロセスまたは 1 組のプロセスのスケジューリングパラメータを管理します。priocntl(2) 呼び出しにより管理できるのは、LWP、単独のプロセス、またはプロセスのグループです。プロセスのグループは、親プロセス、プロセスグループ、セッション、ユーザー、グループ、クラス、または動作中のすべてのプロセスによって識別できます。詳細は、priocntl のマニュアルページを参照してください。

クラス ID を指定した場合、PC_GETCLINFO コマンドはスケジューリングクラス名とパラメータを取得します。このコマンドを使用すると、設定するクラスを想定しないプログラムを作成できます。

PC_SETXPARMS コマンドは、一組のプロセスのスケジューリングクラスとパラメータを設定します。idtypeid の入力引数は、変更するプロセスを指定します。

その他のインタフェースとの関係

あるタイムシェアリングクラスのプロセスの優先順位を変更すると、そのタイムシェアリングクラスのほかのプロセスの動作に影響する可能性があります。この節では、スケジューリングの変更がどのようにほかのプロセスに影響するかについて説明します。

カーネルプロセス

カーネルのデーモンやハウスキーピングプロセスはシステムスケジューリングクラスのメンバーです。ユーザーは、このクラスにプロセスを追加または削除したり、これらのプロセスの優先順位を変更したりすることはできません。ps -cel コマンドを実行すると、すべてのプロセスのスケジューリングクラスが示されます。ps(1) コマンドで -f オプションを指定すると、システムクラスのプロセスには、CLS カラムの SYS と表示されます。

forkexec の使用法

スケジューリングクラス、優先順位、その他のスケジューリングパラメータは、fork(2) インタフェースや exec(2) インタフェースを実行した場合も継承されます。

nice の使用法

nice(1) コマンドと nice(2) インタフェースは、UNIX システムの以前のバージョンと同じ動作になります。これらのコマンドは、タイムシェアリングプロセスの優先順位を変更します。これらのインタフェースでも、数値が小さいほどタイムシェアリング優先順位は高くなります。

プロセスのスケジューリングクラスを変更したり、リアルタイム優先順位を指定したりするには、priocntl(2) を使用します。数値が大きいほど優先順位は高くなります。

init(1M)

init(1M) プロセスは、スケジューラに対しては特殊なケースとして動作します。init(1M) のスケジューラの設定項目を変更するには、idtypeid、または procset 構造体で、init だけをプロセスに指定する必要があります。

スケジューリングとシステム性能

スケジューラは、プロセスをいつどのくらいの時間実行するかを決定します。したがって、スケジューラの動作はシステム性能に大きな影響を与えます。

デフォルトでは、ユーザープロセスはすべてタイムシェアリングプロセスです。priocntl(2) 呼び出しによってのみ、プロセスのクラスが変更できます。

リアルタイムプロセス優先順位は、どのタイムシェアリングプロセスよりも優先順位が高くなっています。リアルタイムプロセスが実行可能である間、タイムシェアリングプロセスやシステムプロセスは実行できません。CPU の制御に失敗することがあるリアルタイムアプリケーションは、その他のユーザーや重要なカーネルハウスキーピングを完全にロックアウトする可能性があります。

プロセスのクラスと優先順位を制御する以外に、リアルタイムアプリケーションは、性能に影響するほかの要因も制御する必要があります。性能にもっとも影響する要因は、CPU、一次メモリー量、入出力スループットです。これらの要因は相互に複雑に関連しています。sar(1) コマンドには、すべての性能要因を表示するオプションがあります。

プロセスの状態変移

リアルタイム制約が厳しいアプリケーションは、プロセスがスワップされたり二次メモリーにページアウトされたりしないようにする必要があります。次の図では、UNIX のプロセスの状態と状態間の変移の概要を示します。

図 4–2 プロセス状態の変移図

 実行中のプロセスは、実行可能またはメモリー内で休眠状態の場合、メモリーに横取りされます。メモリー内のプロセスはスワップされます。

動作中のプロセスは、通常、上記の図の 5 つのうち 1 つの状態にあります。矢印は、プロセスの状態の変化を示します。

プロセスが再度実行可能になった場合、ページングとスワップの両方により、遅延が発生します。タイミング要求が厳しいプロセスにとっては、この遅延は受け入れられないものです。

リアルタイムプロセスにすれば、プロセスの一部がページングされることがあってもスワップはされないため、スワップによる遅延を避けることができます。プログラムは、テキストとデータを一次メモリー内にロックして、ページングとスワップを避けることができます。詳細は、memcntl(2) のマニュアルページを参照してください。ロックできる量はメモリー設定によって制限されます。また、ロックが多すぎると、テキストやデータをメモリー内にロックしていないプロセスが大幅に遅れる可能性があります。

リアルタイムプロセスの性能とその他のプロセスとの性能の兼ね合いは、ローカルな必要性によって異なります。システムによっては、必要なリアルタイム応答を保証するためにプロセスのロックが必要な場合もあります。


注 –

リアルタイムアプリケーションの応答時間については、「ディスパッチ応答時間」を参照してください。