ioprio_get, ioprio_set - I/O
スケジューリングクラスと優先度の設定/取得
int ioprio_get(int which, int who);
int ioprio_set(int which, int who, int ioprio);
注意:
これらのシステムコールには
glibc
ラッパー関数は存在しない。
「注意」の節を参照。
システムコール
ioprio_get() /
ioprio_set() は、(1つ以上の)
スレッドの I/O
スケジューリングクラスと
優先度の取得/設定を行う。
which と
who
引き数でシステムコールの操作対象となるスレッドを指示する。
which 引き数は、
who
をどのように解釈するかを決めるもので、以下のいずれか一つを指定する。
- IOPRIO_WHO_PROCESS
- who
は特定のプロセスやスレッドを特定するためのプロセス
ID かスレッド ID
である。 who が 0
の場合、呼び出し元のスレッドに対して操作が行われる。
- IOPRIO_WHO_PGRP
- who
はプロセスグループ
ID
であり、プロセスグループの全メンバが対象となる。
who が 0 の場合、
呼び出し元がメンバーとなっているプロセスグループに対して操作が行われる。
- IOPRIO_WHO_USER
- who はユーザID
であり、実 UID
に一致する全プロセスが対象となる。
ioprio_get() の呼び出し時に
which に
IOPRIO_WHO_PGRP か
IOPRIO_WHO_USER
が指定され、
who
に一致するプロセスが複数あった場合、
一致するプロセス全体の中で最も高い優先度が返される。
優先度が高いとは、より高い優先度クラスに属している
(
IOPRIO_CLASS_RT
が最も高い優先度クラスで、
IOPRIO_CLASS_IDLE
が最も低い)、もしくは
同じ優先度クラスに属しているが優先度レベルが高い
(優先度番号が小さい方が優先度レベルが高いことを意味する)、
ということである。
ioprio_set() に渡す
ioprio
引き数は、対象となるプロセスに割り当てるスケジューリングクラスと
優先度の両方を指定するビットマスクである。
ioprio
の値を組み立てたり解釈するのに、以下のマクロが利用できる。
- IOPRIO_PRIO_VALUE(class, data)
- スケジューリングクラス
class と優先度 (data)
を与えると、このマクロは
2つの値を組み合わせて、
ioprio
値を生成し、マクロの結果として返す。
- IOPRIO_PRIO_CLASS(mask)
- mask (ioprio 値)
を与えると、このマクロは
I/O
クラス要素、つまり
IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE
のいずれか一つの値を返す。
- IOPRIO_PRIO_DATA(mask)
- mask (ioprio 値)
を与えると、このマクロは優先度
( data) 要素を返す。
スケジューリングクラスと優先度に関する詳しい情報は、
「備考」の節を参照のこと。
I/O
優先度は読み出しと同期書き込み
(
O_DIRECT,
O_SYNC)
に対応している。 I/O
優先度は非同期書き込みには対応していない。なぜなら、
非同期書き込みはメモリ書き換えを行うプログラムの動作
(context) とは
関係なく発行され、そのためプログラム単位の優先度は適用されないから
である。
返り値¶
成功すると、
ioprio_get()
は、
which と
who
で指定された基準に合致した全プロセスで最も高い
I/O
優先度を持つプロセスの
ioprio 値を返す。
エラーの場合、-1
を返し、
errno
にエラーを示す値を設定する。
成功すると、
ioprio_set() は 0
を返す。
エラーの場合、-1
を返し、
errno
にエラーを示す値を設定する。
エラー¶
- EINVAL
- which か ioprio
の値が不正である。
ioprio
用に指定可能なスケジューラクラスと優先度レベルについては
「備考」を参照のこと。
- EPERM
- 呼び出し元プロセスが、指定されたプロセスに
ioprio
を割り当てるのに必要な権限を持っていない。
ioprio_set()
に必要な権限についての詳しい情報は「備考」の節を参照のこと。
- ESRCH
- which と who
で指定された基準に合致するプロセスが見つからなかった。
バージョン¶
これらのシステムコールはカーネル
2.6.13 以降の Linux
で利用可能である。
これらのシステムコールは
Linux 独自である。
glibc
はこれらのシステムコールに対するラッパー関数を提供していない。
syscall(2)
を使って呼び出すこと。
複数のプロセスやスレッドが一つの
I/O
コンテキストを共有する場合がある。
clone(2) を
CLONE_IO
フラグ付きで呼び出した場合にはこの状況となる。
しかしながら、デフォルトでは、一つのプロセスの個々のスレッドは
I/O
コンテキストを共有「しない」。
したがって、
プロセス内のすべてのスレッドの
I/O
優先度を変更したい場合には、
それぞれのスレッドに対して
ioprio_set()
を呼び出す必要がある。
この操作を行うのに必要となるスレッド
ID には
gettid(2) か
clone(2)
が返す値を指定する。
これらのシステムコールは、I/O
優先度に対応した I/O
スケジューラと
組み合わせて使用された場合にのみ効果を持つ。
カーネル 2.6.17
では、この条件を満たすスケジューラは
Completely Fair Queuing (CFQ) I/O
スケジューラだけである。
I/O スケジューラの選択¶
I/O
スケジューラの選択はデバイス単位に行われ、その選択は
スペシャルファイル
/sys/block/<device>/queue/scheduler
経由で行われる。
現在の I/O
スケジューラは
/sys
ファイルシステム経由で参照できる。例えば、以下のコマンドを実行すると、
現在カーネルでロードされているスケジューラの全リストが表示される。
$ cat /sys/block/hda/queue/scheduler
noop anticipatory deadline [cfq]
括弧で囲まれたスケジューラがそのデバイス
(上の例では
hda)
について実際に使用されているスケジューラである。
別のスケジューラを設定するには、このファイルに新しいスケジューラ名を
書き込めばよい。例えば、以下のコマンドを実行すると、デバイス
hda
のスケジューラとして
cfq が設定される。
$ su
Password:
# echo cfq > /sys/block/hda/queue/scheduler
Completely Fair Queuing (CFQ) I/O スケジューラ¶
バージョン 3 (別名 CFQ Time Sliced)
以降、 CPU
スケジューリングと同様の
I/O nice レベルが CFQ
に実装されている。
これらの nice レベルは
3つのスケジューリングクラスに分類でき、
各スケジューリングクラスにつき
1つ以上の優先度レベルが定義されている。
- IOPRIO_CLASS_RT (1)
- これはリアルタイム
I/O クラスである。
このスケジューリングクラスには他のクラスよりも高い優先度が与えられる。
このクラスのプロセスには、常にディスクへのアクセスが優先して
割り当てられる。そのため、この
I/O
クラスを使う際には、
たった一つの
リアルタイム I/O
クラスのプロセスにより
システム全体のディスクアクセスができなくなってしまうことがある
という点に、注意を払う必要がある。
このクラスには、8
段階の class data
(優先度レベル)
がある。
この値は、そのプロセスが
1回のディスクアクセスにどれだけの
時間が必要かを正確に決めるためのものである。
最高のリアルタイム優先度レベルは
0 で、最低は 7
である。
将来的には、優先度レベルは、希望するデータレートを渡すなど、
より直接的に性能条件を反映できるように変更されるかもしれない。
- IOPRIO_CLASS_BE (2)
- これは
ベストエフォート・スケジューリングクラスである。
このクラスは、特定の
I/O
優先度を設定していないプロセスの
デフォルト値である。
class data (優先度レベル)
により、そのプロセスがどの程度の
I/O
帯域を得られるかが決定される。
ベストエフォート・優先度レベルは、CPU
の nice 値 ( getpriority(2) 参照)
と同様のものである。
優先度レベルは、ベストエフォート・スケジューリングクラスの中で
他のプロセスとの相対的な優先度を決定する。
優先度レベルの値の範囲は
0 (最高) から 7 (最低)
である。
- IOPRIO_CLASS_IDLE (3)
- これは idle
スケジューリングクラスである。
このレベルで動作するプロセスは他にディスクアクセスをしようとする
プロセスがない場合にのみ
I/O 時間を取得する。 idle
クラスには class data
(優先度)
は用意されていない。
プロセスにこの優先度を割り当てる際には注意が必要である。
なぜなら、優先度の高いプロセスが常にディスクにアクセスしている場合には
ディスクにアクセスできなくなる可能性があるからだ。
CFQ I/O
スケジューラの更なる情報とサンプルプログラムについては
Documentation/block/ioprio.txt
を参照のこと。
I/O 優先度の設定に必要な許可¶
プロセスの優先度を変更する許可が得られるかどうかは
以下の
2つの条件に基いて決定される。
- プロセスの所有権
- 非特権プロセスは、プロセスの実
UID
が呼び出し元プロセスの実
UID もしくは 実効 UID
と一致するプロセスの
I/O
優先度のみを設定できる。
CAP_SYS_NICE
ケーパビリティを持つプロセスは、どのプロセスの優先度でも変更できる。
- どの優先度に設定しようとしているか
- 非常に高い優先度
(IOPRIO_CLASS_RT)
を設定しようとする場合、
CAP_SYS_ADMIN
ケーパビリティが必要である。
カーネル 2.6.24
以前では、非常に低い優先度
( IOPRIO_CLASS_IDLE)
を設定するためにも
CAP_SYS_ADMIN
ケーパビリティが必要であったが、
Linux 2.6.25
以降ではもはや必要なくなった。
ioprio_set()
はこの両方のルールに従い、条件を満たさない場合、エラー
EPERM で失敗する。
glibc
は、このページに記載された関数プロトタイプやマクロを定義する
適切なヘッダファイルをまだ提供していない。
必要な定義については
linux/ioprio.h を見ればよい。
関連項目¶
ionice(1),
getpriority(2),
open(2),
capabilities(7)
Linux カーネルソース内の
Documentation/block/ioprio.txt
この文書について¶
この man ページは Linux
man-pages
プロジェクトのリリース
3.65 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man-pages/
に書かれている。