kazmax - Linux で自宅サーバー

futex - システムコールの説明 - Linux コマンド集 一覧表

  1. 名前
  2. 書式
  3. 説明
  4. 返り値
  5. エラー
  6. 注意
  7. バージョン
  8. 準拠
  9. 関連項目

名前

futex - 高速ユーザ空間ロック機構のシステムコール

書式


"#include <linux/futex.h>"
"#include <sys/time.h>"
int futex(int *uaddr, int op, int val", const struct timespec *" timeout ,
int *uaddr2, int val3);

説明

futex ()システムコールは、 指定したアドレスの値が変更されるのをプログラムが待つ手段や 特定のアドレスに対して待機中のプロセスを wake (起床) させる手段を提供する (プロセスが異なれば同じメモリに対するアドレスも同じではないかもしれないが、 カーネルは異なる位置にマップされた同じメモリを futex ()で使えるよう内部でマップする)。 典型的には、futex は   futex (7) に記されているように、 共有メモリ中のロックが競合する場合の処理を実装するのに用いられる。

  futex (7) の操作がユーザ空間で競合なく完了しなかった場合、 カーネルに仲裁させるためにシステムコールを呼ぶ必要がある。 仲裁というのは、呼び出しプロセスを sleep (起床待ち) させたり、反対に 待ちプロセスを wake させたりすることを意味する。

この関数を呼び出すプロセスは   futex (7) に記述されているセマンティクスに忠実であることが要求される。 このセマンティクスには移植不可能なアセンブリ命令を書くことが含まれる。 このことは言い換えると futex のユーザのほとんどは実際はライブラリの作者であり、 一般アプリケーションの開発者ではないということである。

uaddr 引数は、カウンタを格納する、 アラインメントの揃った int 型変数を指している必要がある。 実行する操作は op パラメータを介して、値 val とともに渡される。

現在のところ 5 つの操作が定義されている:

FUTEX_WAIT
この操作は futex アドレス uaddr に指定された値 val がまだ格納されているかどうかを不可分操作で検証し、 sleep 状態で この futex アドレスに対して FUTEX_WAKE が実行されるのを待つ。 timeout 引数が NULL でない場合、その内容は 待ち時間の最大値を表す。NULL の場合は無限大を表す。 引数 uaddr2val3 は無視される。
  futex (7) に照らし合わせると、この呼び出しは カウントのデクリメントで負の値 (競合を表す) になった場合に実行され、 別のプロセスがその futex を解放し FUTEX_WAKE の操作を実行するまで sleep する。
FUTEX_WAKE
この操作では指定した futex アドレスに対して待ち状態の (すなわち FUTEX_WAIT 中の) 最大 val 個のプロセスを wake させる。 引数 timeout , uaddr2 , val3 は無視される。
futex (4) に照らし合わせると、 この操作は カウントのインクリメントで待ちプロセスがあると判明し、 futex 値が 1 に設定された (利用可能であることを表す) 場合に実行される。
FUTEX_FD
非同期の wake に対応するため、この操作はファイルディスクリプタを futex に 関連づける。 別のプロセスが FUTEX_WAKE を実行すると、 プロセスは val で渡されたシグナル番号のシグナルを受信する。 呼び出しプロセスは使用後、返されたファイルディスクリプタを クローズしなければならない。 引数 timeout , uaddr2 , val3 は無視される。
競合状態を防止するため、呼び出しプロセスは FUTEX_FD が返ったあと futex が up されたかどうかを確認しなければならない。
FUTEX_REQUEUE (Linux 2.5.70 以降)
この操作は、 FUTEX_WAKE が使われていて、かつ wake されている全てのプロセスが 他の futex を取得する必要がある場合に、 「獣の群れの暴走 (thundering herd)」効果を避けるために導入された。 この呼び出しは val 個のプロセスを wake し、アドレス uaddr2 で futex を待っている他の全てのプロセスを再度キューにいれる。 引数 timeoutval3 は無視される。
FUTEX_CMP_REQUEUE (Linux 2.6.7 以降)
故意に FUTEX_REQUEUE を使う場合に競合が起こるため、 FUTEX_CMP_REQUEUE が導入された。 これは FUTEX_REQUEUE と似ているが、場所 uaddr に値 val3 がまだ保持されているかを最初にチェックする。 保持されていない場合、エラー EAGAIN か返される。 引数 timeout は無視される。

返り値

どの操作が実行されたかによって、返り値は異なる意味を持つ。

FUTEX_WAIT
プロセスが FUTEX_WAKE の呼び出しで wake すると 0 を返す。 タイムアウトの場合、ETIMEOUT が返る。 futex が指定された値と等しくない場合、EWOULDBLOCK が返る。 シグナルを受信すると (または他の偽の wake によって) EINTR を返す。
FUTEX_WAKE
wake したプロセスの数を返す。
FUTEX_FD
futex に関連づけられた新たなファイルディスクリプタを返す。
FUTEX_REQUEUE
wake したプロセスの数を返す。
FUTEX_CMP_REQUEUE
wake したプロセスの数を返す。

エラー

EACCES
futex メモリに読み込みアクセス権がなかった。
EAGAIN
FUTEX_CMP_REQUEUE で予期しない futex 値が見つかった (これは競合を示しているかもしれない。 この場合は安全な FUTEX_WAKE を使うこと)。
EFAULT
ユーザ空間から timeout の情報を取得する際にエラーが発生した。
EINVAL
操作が定義されていない。またはページ・アラインメントでエラーが発生した。
ENFILE
オープンされているファイルの総数がシステムの制限に達した。

注意

繰り返すが、裸の futex はエンドユーザが容易に使うことのできる概念として 意図されたものではない。 実装者は、アセンブリ言語に慣れており、以下に挙げる futex ユーザ空間ライブラリの ソースを読み終えていることが要求される。

バージョン

最初の futex 対応は Linux 2.5.7 で組み込まれたが、 上記のセマンティクスとは異なる。 ここで示されているセマンティクスを持つ 4 つの引数のシステムコールは、Linux 2.5.40 で導入された。 Linux 2.5.70 では 1 つの引数が追加された。 Linux 2.6.7 では 6 番目の引数が追加された。 これは汚く、s390 アーキテクチャ上の特別のものである。

準拠

このシステムコールは Linux 独自である。

関連項目

futex (7), `Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux' (proceedings of the Ottawa Linux Symposium 2002), futex の使用例ライブラリ, futex-*.tar.bz2 <URL:ftp://ftp.nl.kernel.org:/pub/linux/kernel/people/rusty/>.