スポンサーリンク

KQUEUE(2) FreeBSD システムコールマニュアル KQUEUE(2)

名称

kqueue, kevent − カーネルイベント通知メカニズム

ライブラリ

標準 C ライブラリ (libc, −lc)

書式

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

int

kqueue(void);

int

kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout);

EV_SET(&kev, ident, filter, flags, fflags, data, udata);

解説

kqueue() システムコールは、フィルタと呼ばれる小さなカーネルコードの実行結 果に基づき、イベントの発生やある状態の成立をユーザに通知する一般的な方法 を提供します。 kevent は (ident, filter) のペアによって識別されます。ここ で、ident は識別子、filter はフィルタを表します。 1 つの kqueue には、同 じ kevent が複数存在することはできません。

フィルタは、kevent の初期登録時に以前から存在した状態を検出するために実行 されます。また、あるイベントが評価のためにフィルタに渡されるたびに実行さ れます。状態を報告すべきとフィルタが決定した場合には、その kevent はユー ザが回収できるように kqueue に置かれます。

ユーザが kqueue から kevent を回収しようとしたときにも、フィルタが実行さ れます。フィルタの実行により、そのイベントをトリガした状態が成立していな いことが示された場合には、その kevent は kqueue から削除され、ユーザに渡 されません。

フィルタをトリガするイベントが複数ある場合でも、 kqueue の中に kevent が 複数置かれるわけではありません。代わりに、フィルタは複数のイベントを単一 の kevent 構造体へ集めます。ファイル記述子に対する close() の呼び出しは、 その記述子を参照しているあらゆる kevent を削除します。

kqueue() システムコールは新規のカーネルイベントキューを生成して記述子を返 します。キューは fork(2) で生成された子プロセスには継承されません。しかし ながら、 RFFDG フラグなしで rfork(2) が呼び出された場合には、記述子テーブ ルが共有され、2 つのプロセス間で kqueue の共有が可能になります。

kevent() システムコールは、キューにイベントを登録し、保留中のあらゆるイベ ントをユーザに返すために使用されます。 changelist 引数は kevent 構造体の 配列へのポインタです。この構造体は <sys/event.h> で定義されています。保留 中のイベントをキューから読み取る前に、 changelist に含まれている全ての変 更を適用します。 nchanges 引数は changelist の大きさを与えます。 eventlist 引数は kevent 構造体の配列へのポインタです。 nevents 引数は eventlist の大きさを決定します。 nevents が 0 の時には、 select(2) とは 違って、たとえ timeout がある場合でも kevent() はすぐに戻ります。 timeout が NULL でないポインタの場合には、timespec 構造体であると解釈されて、イベ ントを待つ最大待ち時間を指定します。 timeout が NULL ポインタの場合には、 kevent() は無期限に待ちます。ポーリングの効果を得るためには、 timeout 引 数に、0 を示す timespec 構造体を指す非 NULL のポインタを与えるべきです。 changelisteventlist 用に同じ配列を使うことができます。

EV_SET() マクロは kevent 構造体の初期化を簡単にするために用意されていま す。

kevent 構造体は次のように定義されています:

struct kevent {

uintptr_t ident;

/* このイベントの識別子 */

short

filter;

/* イベントのフィルタ */

u_short

flags;

/* kqueue のアクションフラグ */

u_int

fflags;

/* フィルタフラグ値 */

intptr_t data;

/* フィルタデータ値 */

void

*udata;

/* 不透明なユーザデータ識別子 */

};

struct kevent のフィールドは以下のとおりです:

       ident

このイベントを識別するために使用される値です。厳密な解釈は結び 付けられたフィルタにより決定されますが、普通はファイル記述子と して解釈されます。

filter
このイベントを処理するために使用されるカーネルフィルタを識別し ます。あらかじめ定義されたシステムフィルタは後述してあります。

flags
イベント発生時に実行するべきアクションです。

fflags
フィルタ固有のフラグです。

data
フィルタ固有のデータの値です。

udata
変更されずにカーネルを通して渡される不透明なユーザ定義の値で す。

flags フィールドは以下の値を含むことができます:

EV_ADD
イベントを kqueue に追加します。既存のイベントを再び追加す ると、元のイベントのパラメータが変更されます。重複するエン トリができるわけではありません。イベントを追加する と、EV_DISABLE フラグによって上書きされない限りは自動的に 有効にされます。

EV_ENABLE
イベントがトリガされた場合に、 kevent() がそのイベントを返 すことを許可します。

EV_DISABLE
イベントを無効にします。これにより kevent() はそのイベント を返さなくなります。フィルタ自身は無効にされません。

EV_DELETE
kqueue からイベントを削除します。ファイル記述子に結び付け られているイベントは、その記述子の最後のクローズ時に自動的 に削除されます。

EV_ONESHOT
フィルタが最初トリガされたときにのみ、イベントが返るように します。ユーザがイベントを kqueue から回収した後で、そのイ ベントは削除されます。

EV_CLEAR
ユーザがイベントを回収した後に、その状態をリセットします。 これは現在の状態ではなく、状態の変化を報告するフィルタに有 用です。幾つかのフィルタは内部でこのフラグを自動的にセット しているかもしれないことに注意してください。

EV_EOF
そのフィルタ固有の EOF 状態であることを示すために、フィル タがこのフラグをセットすることがあります。

EV_ERROR
後述の 戻り値を参照してください。

あらかじめ定義されたシステムフィルタを次に示します。引数は kevent 構造体 の fflags および data フィールドを経由してやりとりすることができます。

EVFILT_READ
識別子に記述子を引数として取ります。読取り可能なデータがあ るときに戻ります。このフィルタの振舞いは、その記述子の型に より少し異なります。

ソケット
事前に listen() に渡されたソケットの場合、保留中の次の 接続があるときに戻ります。 data には listen のバックロ グ (backlog) の大きさが入っています。

その他のソケット記述子の場合、ソケットバッファの SO_RCVLOWAT の値を基準にして、読み取るデータがあるとき に戻ります。フィルタを追加するときに、 fflags に NOTE_LOWAT を設定し data に新しい最低基準値を指定する ことにより、この値を、フィルタごとの最低基準値で上書き することが可能です。戻るときには、 data には読取り可能 なプロトコルデータのバイト数が入っています。

ソケットの読取り側が切断された場合には、フィルタは flags に EV_EOF も設定します。ここでエラーが起きた場合 には、 fflags にソケットエラーを返します。ソケットバッ ファの中に保留中のデータが残っていても、 (接続が切れた ことを示す) EOF が返されることがあります。

vnode
ファイルポインタがファイルの最後 (EOF) でないときに戻 ります。 data は現在位置からファイルの最後 (EOF) まで のオフセットが入っています。この値は負であるかもしれま せん。

FIFO とパイプ
読み取るべきデータがあるときに戻ります。 data には有効 なバイト数が入っています。

最後の書込み側が切断したときに、フィルタは flags に EV_EOF をセットします。 EV_CLEAR を渡すことで、このフ ラグをクリアすることができ、フィルタはデータが読み取る ようになるのを戻らずに再び待ちます。

BPF デバイス
BPF バッファが一杯になったとき、BPF タイムアウトが満了 したとき、または BPF の ‘‘直接モード’’ が有効で読み込 むべきデータがあるときに、戻ります。このときの data に は利用可能なバイト数が入ります。

EVFILT_WRITE
識別子に記述子を引数として取ります。その記述子が書込み可能 になるたびに戻ります。ソケット、パイプおよび FIFO では、 data には書込みバッファの残り領域の大きさが入っています。 読取り側が切断したときに、フィルタは EV_EOF をセットしま す。 FIFO の場合、EV_CLEAR を使いこれをクリアすることがで きます。このフィルタは vnode または BPF デバイスをサポート していないことに注意してください。

ソケットの場合、最低基準値およびソケットエラーの取り扱いは EVFULT_READ の場合と同じです。

EVFILT_AIO
非同期入出力要求の sigevent 部分の、 sigev_notify_kqueue にはイベントを付加する kqueue の記述子を入れ、 sigev_value には udata の値を入れ、 sigev_notify には SIGEV_KEVENT を 入れて、非同期入出力要求を埋めます。 aio_*() システムコー ルが呼び出されたとき、そのイベントは指定された kqueue に登 録されます。 aio_*() システムコールによって返された struct aiocbident 引数にセットします。このフィルタは aio_error と同様の条件で戻ります。

別の方法として、 ident に kqueue 記述子を入れて kevent 構 造体を初期化し、そのアドレスを非同期要求の aio_lio_opcode フィールドに置くことも可能です。しかしながら、このアプロー チは 64 ビットポインタのアーキテクチャでは動作しないでしょ うし、あてにするべきではありません。

EVFILT_VNODE
ファイル記述子を識別子に、監視するイベントを fflags に引数 として取ります。指定した記述子に対し要求されたイベントが 1 つ以上発生したときに戻ります。監視するイベントを以下に示し ます:

NOTE_DELETE
記述子が参照するファイルに対し unlink() シ ステムコールが呼ばれました。

NOTE_WRITE
記述子が参照するファイルに対し書込みが起こ りました。

NOTE_EXTEND
記述子が参照するファイルのサイズが拡張され ました。

NOTE_ATTRIB
記述子が参照するファイルの属性が変更されま した。

NOTE_LINK
ファイルのリンク数が変更されました。

NOTE_RENAME
記述子が参照するファイルがリネームされまし た。

NOTE_REVOKE
ファイルへのアクセスが revoke(2) によって無 効にされたか、もしくは、下位層のファイルシ ステムがマウントされていません。

戻るときに、 fflags にフィルタをトリガしたイベントが入って います。

EVFILT_PROC
監視するプロセス ID を識別子に、監視するイベントを fflags に引数として取ります。要求されたイベントを 1 つ以上プロセ スが実行するときに戻ります。あるプロセスが他のプロセスを正 常に見ることができる場合には、イベントをそのプロセスに結び 付けることができます。監視するイベントを次に示します:

NOTE_EXIT
プロセスが終了しました。

NOTE_FORK
プロセスが fork() を呼びました。

NOTE_EXEC
プロセスが execve(2) または類似の呼び出し により、新規のプロセスを実行しました。

NOTE_TRACK
fork
() の呼び出しを越えて、プロセスを追跡 します。親プロセスは fflags フィールドに NOTE_TRACK をセットして戻り、一方、子プロ セスは fflags に NOTE_CHILD を data に親 プロセスの PID をセットし戻ります。

NOTE_TRACKERR
このフラグは、システムが子プロセスへのイ ベントを結び付けることができなかったとき に戻ります。通常、これは資源の制限により 生じます。

戻るときに、 fflags はフィルタをトリガしたイベントが入って います。

EVFILT_SIGNAL
監視するシグナル番号を識別子に引数として取ります。与えられ たシグナルがプロセスに配送されたときに戻ります。これは signal() および sigaction() の仕組みと共存し、低い優先順位 を持っています。たとえそのシグナルが SIG_IGN とマークされ ていたとしても、フィルタはプロセスに配送されようとしたシグ ナル全てを記録します。通常のシグナル配送処理の後に、イベン ト通知が発生します。 data には kevent() を最後に呼び出して からのシグナル発生の回数が返ります。このフィルタは内部で自 動的に EV_CLEAR フラグをセットします。

EVFILT_TIMER
ident
で識別される、任意のタイマを設定します。タイマを追加 する場合、 data はタイムアウトをミリ秒単位で指定します。 EV_ONESHOT を指定しない限り、タイマは周期的です。 data に は、 kevent() を最後に呼び出してからのタイムアウトの回数が 返ります。このフィルタは内部で自動的に EV_CLEAR フラグを セットします。

EVFILT_NETDEV
識別子としてネットワークインタフェースの記述子を取り、監視 するイベントを fflags に取ります。記述子上に要求されたイベ ントが 1 つ以上発生したとき、戻ります。監視可能なイベント は次の通りです:

NOTE_LINKUP
リンクがアップ。

NOTE_LINKDOWN
リンクがダウン。

NOTE_LINKINV
リンク状態が無効。

戻るとき、フィルタをトリガしたイベントが fflags に格納され ます。

戻り値

kqueue() システムコールは新規のカーネルイベントキューを生成し、ファイル記 述子を返します。カーネルイベントキューの生成時にエラーがあった場合には、 値 -1 が返されて errno がセットされます。

kevent() システムコールは eventlist に配列されているイベントの数を返しま す。この数は、最大 nevents で与えられた値までです。 changelist の要素の処 理中にエラーが発生し、かつ eventlist に十分な余地がある場合には、 flags に EV_ERROR がセットされ、 data にシステムエラーがセットされたイベント が、 eventlist に置かれます。さもなければ、 -1 が返され、 errno がエラー 状態を示すためにセットされます。時間切れの場合には、 kevent() は 0 を返し ます。

エラー

kqueue() システムコールは以下の場合に失敗します:

       [ENOMEM]

カーネルがカーネルキューのための十分なメモリの割り当て に失敗しました。

[EMFILE]
プロセスの記述子テーブルが満杯です。

[ENFILE]
システムファイルテーブルが満杯です。

kevent() 関数は以下の場合に失敗します:

[EACCES]
プロセスがフィルタを登録する権限を持っていません。

[EFAULT]
kevent
構造体の読取りまたは書込みでエラーがありまし た。

[EBADF]
指定された記述子が有効ではありません。

[EINTR]
時間切れ前や、戻るための何らかのイベントが kqueue に置 かれる前に、シグナルが配送されました。

[EINVAL]
指定されたタイムリミットまたはフィルタが無効です。

[ENOENT]
修正または削除されるべきイベントが見つかりません。

[ENOMEM]
イベント登録のためのメモリがありません。

[ESRCH]
結び付けるために指定したプロセスが存在しません。

関連項目

aio_error(2), aio_read(2), aio_return(2), poll(2), read(2), select(2), sigaction(2), write(2), signal(3)

歴史

kqueue() および kevent() システムコールは FreeBSD 4.1 ではじめて登場しま した。

作者

kqueue() システムと、このマニュアルページは Jonathan Lemon ⟨jlemon@FreeBSD.org⟩ が書きました。

バグ

現在は、UFS ファイルシステムに属さない vnode(9) を監視することができませ ん。

EVFILT_NETDEV フィルタが現在実装されているのは、LINKUP と LINKDOWN の操作 に miibus(4) ドライバを使用しているデバイスに対してのみです。そのため、非 イーサネットデバイスに対しては動作しません。

timeout の値は 24 時間に制限されています。より長いタイムアウトは暗黙のう ちに 24 時間として再解釈されます。

FreeBSD 10.0 April 14, 2000 FreeBSD 10.0

スポンサーリンク