Provided by: manpages-ja-dev_0.5.0.0.20140515+dfsg-2_all 

名前
fcntl - ファイルディスクリプタの操作を行う
書式
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
説明
fcntl() は、オープンされたファイルディスクリプタ fd に関して下記の操作を行う。操作は cmd によって決まる:
fcntl() はオプションとして第三引き数をとることができる。 第三引き数が必要 かどうかは cmd により決まる。必
要な引き数の型は cmd 名の後ろの括弧内で 指定されている (ほとんどの場合、必要な型は int であり、この引き数
を表すの に arg という名前を使っている)。引き数が必要ない場合には void が指定さ れている。
ファイルディスクリプタの複製
F_DUPFD (int)
利用可能なファイルディスクリプタのうち、 arg 以上で最小のものを探し、 fd のコピーとする。これは別
の形の dup2(2) である。 dup2(2) では指定されたディスクリプタが使われる点が違う。
成功すると、新しいディスクリプタが返される。
詳細は dup(2) を参照のこと。
F_DUPFD_CLOEXEC (int; Linux 2.6.24 以降)
F_DUPFD と同様だが、それに加えて複製されたディスクリプタに対して close-on-exec フラグをセットす
る。 このフラグを指定することで、プログラムは FD_CLOEXEC フラグをセットするために fcntl() の
F_SETFD 操作を追加で行う必要がなくなる。 このフラグがなぜ有用かについては、 open(2) の O_CLOEXEC
の説明を参照のこと。
ファイルディスクリプタフラグ
以下のコマンドを使って、ファイルディスクリプタに関連するフラグ を操作することができる。 現在のところ、定
義されているフラグは一つだけである: FD_CLOEXEC (close-on-exec フラグ)。 FD_CLOEXEC ビットが 0 なら、ファ
イルディスクリプタは execve(2) を行ってもオープンされたままだが、そうでない場合はクローズされる。
F_GETFD (void)
ファイルディスクリプタフラグを読み出す。 arg は無視される。
F_SETFD (int)
ファイルディスクリプタフラグに arg で指定した値を設定する。
マルチスレッドプログラムでは、 fcntl() の F_SETFD を使って close-on-exec フラグを設定するのと同時に、 別
のスレッドで execve(2) と fork(2) を実行することは、競合条件次第では、 そのファイルディスクリプタが子プロ
セスで実行されるプログラムに意図せず見えてしまうという危険性がある。 詳細とこの問題への対処法については
open(2) の O_CLOEXEC フラグの議論を参照のこと。
ファイル状態フラグ
オープンファイル記述 (open file description) には、 ファイル記述毎に設定される状態フラグがいくつかあ
る。これらのフラグは open(2) によって初期化され、 fcntl(2) により変更することもできる。これらは、
(dup(2), fcntl(F_DUPFD), fork(2) などで) 複製されたファイルディスクリプタ同士は 同じオープンファイル記述
を参照する。 そのため、 同じファイル状態フラグが共有される。
ファイル状態フラグとその意味は open(2) で説明されている。
F_GETFL (void)
ファイルのアクセスモードとファイル状態フラグを取得する。 arg は無視される。
F_SETFL (int)
ファイル状態フラグに arg で指定された値を設定する。 arg のうち、ファイルのアクセスモード
(O_RDONLY, O_WRONLY, O_RDWR) とファイル作成フラグ (すなわち O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC)
に関するビットは無視される。 Linux では、このコマンドで変更できるのは O_APPEND, O_ASYNC, O_DIRECT,
O_NOATIME, O_NONBLOCK フラグだけである。フラグ O_DSYNC, O_SYNC を変更することはできない。下記の「
バグ」を参照。
アドバイザリロック
F_SETLK, F_SETLKW, F_GETLK は、レコードロックの獲得/解放/テストのために使用する (レコードロックはファイ
ルセグメントロックや ファイル領域ロックとも呼ばれる)。 三番目の引き数 lock は、以下に示すフィールドを含む
構造体へのポインタである (フィールドの順序は関係なく、構造体に他のフィールドがあってもよい)。
struct flock {
...
short l_type; /* Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock
(F_GETLK only) */
...
};
この構造体の l_whence, l_start, l_len フィールドで、ロックを行いたいバイト範囲を指定する。 ファイルの末尾
より後ろのバイトをロックすることはできるが、 ファイルの先頭より前のバイトをロックすることはできない。
l_start はロックを行う領域の開始オフセットである。 その意味は l_whence により異なる: l_whence が SEEK_SET
の場合はファイルの先頭からのオフセット、 l_whence が SEEK_CUR の場合は現在のファイルオフセットからのオフ
セット、 l_whence が SEEK_END の場合はファイルの末尾からのオフセットと解釈される。 後ろの2つの場合には、
ファイルの先頭より前にならない範囲で、 l_start に負の値を指定することができる。
l_len はロックしたいバイト数を示す。 l_len が正の場合、ロックされるバイト範囲は l_start 以上
l_start+l_len-1 以下となる。 l_len に 0 を指定した場合は特別な意味を持つ: l_whence and l_start で指定され
る位置からファイルの末尾までの全てのバイトをロックする (ファイルがどんなに大きくなったとしてもファイルの
末尾までロックする)。
POSIX.1-2001 では、負の値の l_len をサポートする実装を認めている (必須ではない)。 l_len が負の場合、ロッ
クされるバイト範囲は l_start+l_len 以上 l_start-1 以下となる。 この動作はカーネル 2.4.21 以降および
2.5.49 以降の Linux で サポートされている。
l_type フィールドは、ファイルに対して読み出しロック (F_RDLCK) と書き込みロック (F_WRLCK) のどちらを 設
定するかを指定する。 ファイルのある領域に対して、読み出しロック (共有ロック) を保持できる プロセス数に制
限はないが、書き込みロック (排他ロック) を保持できる のは一つのプロセスだけである。排他ロックを設定する
と、(共有ロックか 排他ロックにかかわらず) 他のロックは何も設定できない。 一つのプロセスは、ファイルのある
領域に対して一種類のロックしか保持できない。 新規のロックがロックが設定されている領域に対して適用される
と、既存のロック は新規のロックの種別に変換される (新規のロックで指定されたバイト範囲が既存ロックの範囲と
一致する場合以外では、 変換の過程で既存のロックの分割、縮小、結合が行われることがある)。
F_SETLK (struct flock *)
(l_type が F_RDLCK か F_WRLCK の場合は) ロックの獲得を、 (F_UNLCK の場合は) ロックの解放を、 flock
構造体のフィールド l_whence, l_start, l_len で指定された範囲のバイトに対して行う。 指定されたロッ
クが他のプロセスが設定しているロックと衝突する場合は、 -1 を返し、 errno に EACCES か EAGAIN を設
定する。
F_SETLKW (struct flock *)
F_SETLK と同様だが、こちらではそのファイルに対して衝突するロックが 適用されていた場合に、そのロッ
クが解放されるのを待つ点が異なる。 待っている間にシグナルを受けた場合は、システムコールは中断さ
れ、 (シグナルハンドラが戻った直後に) 返り値 -1 を返す (また errno に EINTR が設定される;
signal(7) 参照)。
F_GETLK (struct flock *)
このコールの呼び出し時には、 lock にはそのファイルに適用しようとするロックに関する情報が入ってい
る。 ロックを適用できる場合には、 fcntl() は実際にはロックを行わず、構造体 lock の l_type フィー
ルドに F_UNLCK を設定し、他のフィールドは変更せずに、復帰する。 違う種別のロックが (一つもしくは複
数) 適用されていて ロックを適用できないような場合には、 fcntl() は、原因となったロックの一つにつ
いての詳細情報を構造体 lock のフィールド l_type, l_whence, l_start, l_len に格納し、また l_pid に
ロックを保持しているプロセスの PID を設定して、復帰する。 F_GETLK が返す情報は呼び出し元がその情報
を使用するときにはすでに古くなっている可能性がある点に注意すること。
読み出しロックを適用するには、 fd は読み出し用にオープンされていなければならない。 書き込みロックを適用す
るには、 fd は書き込み用にオープンされていなければならない。 読み書き両方のロックを適用するには、読み書き
両用で ファイルをオープンしなければならない。
レコードのロックは、 F_UNLCK により明示的に削除されるだけでなく、 プロセスが終了したときや、ロックが適用
されているファイルを参照している ファイルディスクリプタのいずれかがクローズされた場合にも解放される。 こ
のロックの解放は自動的に行われる。 この動作はまずい: あるプロセスが /etc/passwd や /etc/mtab といったファ
イルにロックを適用しているときに、 あるライブラリ関数が何かの理由で同じファイルを open, read, close する
と、そのファイルへのロックが失われることになる。
レコードのロックは fork(2) で作成された子プロセスには継承されないが、 execve(2) の前後では保存される。
stdio(3) ではバッファリングが行われるので、 stdio 関連の関数ではレコードのロックの使用は回避される; 代わ
りに read(2) や write(2) を使用すること。
強制ロック (mandatory locking)
上述のロックにはアドバイザリロック (advisory lock) と強制ロック (mandatory lock) の二種類があるが、デフォ
ルトではアドバイザリロックとなる。
アドバイザリロックに強制力はなく、協調して動作するプロセス間でのみ 有効である。
強制ロックは全てのプロセスに対して効果がある。 あるプロセスが互換性のない強制ロックが適用されたファイル領
域に対して (read(2) や write(2) により) 互換性のないアクセスを実行しようとした場合、 アクセスの結果は
そのファイルのオープンファイル記述で O_NONBLOCK フラグが有効になっているかにより決まる。 O_NONBLOCK フラ
グが有効になっていないときは、ロックが削除されるか、 ロックがアクセスと互換性のあるモードに変換されるま
で、 システムコールは停止 (block) される。 O_NONBLOCK フラグが有効になっているときは、システムコールはエ
ラー EAGAIN で失敗する。
強制ロックを使用するためには、ロック対象のファイルが含まれるファイルシステム と、ロック対象のファイル自身
の両方について、強制ロックが有効になっていなけれ ばならない。ファイルシステムについて強制ロックを有効にす
るには、 mount(8) に "-o mand" オプションを渡すか、 mount(2) に MS_MANDLOCK フラグを指定する。ファイル
について強制ロックを有効にするには、 そのファイルのグループ実行許可 (group execute permission) を無効と
し、 かつ set-group-ID 許可ビットを有効にする (chmod(1) と chmod(2) を参照)。
Linux の強制ロックの実装は信頼性に欠けるものである。 下記の「バグ」の節を参照のこと。
シグナルの管理
F_GETOWN, F_SETOWN, F_GETOWN_EX, F_SETOWN_EX, F_GETSIG, F_SETSIG は、I/O が利用可能になったことを示すシグ
ナルを管理するために使用される。
F_GETOWN (void)
ファイルディスクリプタ fd のイベントに対するシグナル SIGIO および SIGURG を受けているプロセスのプ
ロセスID かプロセスグループを (関数の結果として) 返す。 プロセスID は正の値として返される。 プロセ
スグループID は負の値として返される (下記のバグの章を参照)。 arg は無視される。
F_SETOWN (int)
ファイルディスクリプタ fd のイベント発生を知らせるシグナル SIGIO や SIGURG を受けるプロセスの プロ
セス ID またはプロセスグループID を arg で指定された ID に設定する。 プロセスID は正の値として指定
し、 プロセスグループID は負の値として指定する。 ほとんどの場合、呼び出し元プロセスは所有者として
自分自身を指定する (つまり arg に getpid(2) を指定する)。
fcntl() の F_SETFL コマンドを使用してファイルディスクリプタに O_ASYNC 状態フラグを設定した場合に
は、そのファイルディスクリプタへの 入出力が可能になる度に SIGIO シグナルが送られる。 F_SETSIG は
SIGIO 以外の別のシグナルの配送を受けられるように するのにも使うことができる。 許可 (permission) の
チェックで失敗した場合には、 シグナルは黙って捨てられる。
F_SETOWN により指定された所有者のプロセス (またはプロセスグループ) に シグナルを送る際には、
kill(2) に書かれているのと同じ許可のチェックが行われる。 このとき、シグナルを送信するプロセスは
F_SETOWN を使ったプロセスである (但し、下記の「バグ」の章を参照のこと)。
ファイルディスクリプタがソケットを参照している場合は、 F_SETOWN を使用して、ソケットに帯域外
(out-of-band) データが届いた時に SIGURG シグナルを配送する相手を選択することもできる (SIGURG が送
られた場合には select(2) がソケットが「特別な状態」にあると報告することだろう)。
バージョン 2.6.11 以前の 2.6.x カーネルでは、以下に示す動作であった。
スレッドグループをサポートしているスレッドライブラリ (例えば NPTL) を 使って動作しているマ
ルチスレッドプロセスで F_SETSIG に 0 以外の値を指定した場合、 F_SETOWN に正の値を渡すと、そ
の意味が違ってくる: プロセス全体を示すプロセスID ではなく、プロセス内の特定の スレッドを示
すスレッドID と解釈される。 したがって、 F_SETSIG を使う場合には、きちんと結果を受け取るに
は、 F_SETOWN に渡す値を getpid(2) ではなく gettid(2) の返り値にする必要があるだろう。 (現
状の Linux スレッド実装では、メインスレッドのスレッドID は そのスレッドのプロセスID と同じ
である。つまり、 シグナルスレッドのプログラムではこの場合 gettid(2) と getpid(2) は全く同
じように使うことができる。) ただし、注意すべき点として、この段落で述べたことは、 ソケット
の帯域外データが届いたときに生成される SIGURG シグナルにはあてはまらない。 このシグナルは常
にプロセスかプロセスグループに送られ、 送信先は F_SETOWN に渡された値にしたがって決められ
る。
上記の動作は、Linux 2.6.12 で図らずも削除され、 元に戻されない予定である。 Linux 2.6.32 以降で、特
定のスレッド宛にシグナル SIGIO と SIGURG を送るには F_SETOWN_EX を使うこと。
F_GETOWN_EX (struct f_owner_ex *) (Linux 2.6.32 以降)
直前の F_SETOWN_EX 操作で定義された現在のファイルディスクリプタの所有者設定 を返す。情報は arg が
指す構造体に格納されて返される。構造体は以下の通りである。
struct f_owner_ex {
int type;
pid_t pid;
};
type フィールドは、 F_OWNER_TID , F_OWNER_PID , F_OWNER_PGRP のいずれか一つの値となる。 pid フィー
ルドは、スレッド ID、プロセス ID、プロセスグループ ID を 表す正の整数である。詳細は F_SETOWN_EX を
参照。
F_SETOWN_EX (struct f_owner_ex *) (Linux 2.6.32 以降)
この操作は F_SETOWN と同様の処理を行う。 この操作を使うと、I/O が利用可能になったことを示すシグナ
ルを、 特定のスレッド、プロセス、プロセスグループに送ることができる ようになる。 呼び出し元は、
arg 経由でシグナルの配送先を指定する。 arg は f_owner_ex 構造体へのポインタである。 type フィール
ドは以下のいずれかの値を取り、 この値により pid がどのように解釈されるかが規定される。
F_OWNER_TID
スレッド ID が pid で指定された値のスレッドにそのシグナルを送る (スレッド ID は clone(2)
や gettid(2) の呼び出しで返される値である)。
F_OWNER_PID
ID が pid で指定された値のプロセスにそのシグナルを送る。
F_OWNER_PGRP
ID が pid で指定された値のプロセスグループにそのシグナルを送る。 (F_SETOWN と異なり、プロセ
スグループ ID には正の値を指定する点に注意すること。)
F_GETSIG (void)
入力や出力が可能になった場合に送るシグナルを (関数の結果として) 返す。 値ゼロは SIGIO を送ることを
意味する。 (SIGIO を含む) 他の値はいずれも、 SIGIO の代わりに送るシグナル番号を表す。 後者の場
合、シグナルハンドラを SA_SIGINFO フラグ付きで設定すれば、ハンドラで追加の情報を得ることができる。
arg は無視される。
F_SETSIG (int)
入力や出力が可能になった場合に送るシグナルを arg に指定された値に設定する。 値ゼロは SIGIO を送る
ことを意味する。 (SIGIO を含む) 他の値はいずれも、 SIGIO の代わりに送るシグナル番号を表す。 後者の
場合、シグナルハンドラを SA_SIGINFO フラグ付きで設定すれば、 ハンドラで追加の情報を得ることができ
る。
F_SETSIG にゼロ以外の値を設定し、シグナルハンドラに SA_SIGINFO フラグを設定すると、 (sigaction(2)
を参照) I/O イベントに関する追加の情報が siginfo_t 構造体でシグナルハンドラへ渡される。 si_code
フィールドが示すシグナルの原因が SI_SIGIO である場合、 si_fd フィールドにはイベントに対応するファ
イルディスクリプタが入っている。 それ以外の場合は、どのファイルディスクリプタが利用可能かを示す情
報は ないので、どのファイルディスクリプタで I/O が可能かを判断するためには 通常の機構 (select(2),
poll(2), O_NONBLOCK を設定した read(2) など) を使用しなければならない。
リアルタイムシグナル (値が SIGRTMIN 以上) を選択している場合は、 同じシグナル番号を持つ複数の I/O
イベントがキューに入ることがある (キューに入れるかどうかは利用可能なメモリに依存している)。 上記と
同様、 SA_SIGINFO が設定されている場合、シグナルハンドラのための追加の情報が得られる。
以下の点に注意すること。 Linux では一つのプロセスに対してキューに入れられるリアルタイム シグナルの
数に上限が設けられており (getrlimit(2) と signal(7) を参照)、この上限に達するとカーネルは SIGIO
シグナルを配送する。この SIGIO シグナルは、指定されたスレッドではなくプロセス全体に送られる。
これらの機構を使用することで、ほとんどの場合で select(2) や poll(2) を使用せずに完全な非同期 I/O を実装
することができる。
O_ASYNC の使用方法は BSD と Linux に特有である。 POSIX.1 で規定されている F_GETOWN と F_SETOWN の使用方法
は、ソケットに対する SIGURG シグナルとの組み合わせだけである (POSIX は SIGIO シグナルは規定していない)。
F_GETOWN_EX, F_SETOWN_EX, F_GETSIG, F_SETSIG は Linux 固有である。POSIX には、同様のことを行うために、非
同期 I/O と aio_sigevent 構造体がある。Linux では、GNU C ライブラリ (Glibc) の一部として これらも利用可能
である。
リース (leases)
(Linix 2.4 以降で利用可能) F_SETLEASE は、 fd が参照するオープンファイル記述に対して新しいリースを設定す
るのに使用される。 F_GETLEASE は、 fd が参照するオープンファイル記述に対して設定されている 現在のリースを
取得するのに使用される。 ファイルのリースにより、 あるプロセス ("lease breaker") がそのファイルディスクリ
プタが参照 しているファイルに対して open(2) や truncate(2) を行おうとした際に、リースを保持しているプロ
セス ("lease holder") へ (シグナルの配送による) 通知が行われるという機構が提供される。
F_SETLEASE (int)
arg の内容に基いてファイルのリースの設定、削除を行う。整数 arg には以下の値が指定できる:
F_RDLCK
読み出しリースを取得する。これにより、 そのファイルが書き込み用にオープンされたり、ファイル
が切り詰められた場合に、 呼び出し元のプロセスに通知が行われるようになる。 読み出しリースを
設定できるのは、読み出し専用でオープンされている ファイルディスクリプタに対してのみである。
F_WRLCK
書き込みリースを取得する。これにより、 (読み出し用か書き込み用にかかわらず) そのファイルが
オープンされたり、 ファイルが切り詰められた場合に、呼び出し元のプロセスに通知が行われるよう
になる。 書き込みリースは、そのファイルに対するオープンされたファイルディスクリプタが 他に
ない場合にのみ設定できる。
F_UNLCK
そのファイルからリースを削除する。
リースはオープンファイル記述に対して関連付けられる (open(2) 参照)。 つまり、 (fork(2) や dup(2) などに
より作成された) ファイルディスクリプタの複製は同じリースを参照し、 複製も含めたどのファイルディスクリプタ
を使ってもこのリースを変更したり 解放したりできる。 また、これらのファイルディスクリプタのいずれかに対し
て F_UNLCK 操作が明示的に実行された場合や、すべてのファイルディスクリプタが 閉じられた場合にも、リースは
解放される。
リースの取得は通常のファイル (regular file) に対してのみ可能である。 非特権プロセスがリースを取得できるの
は、UID (所有者) がプロセスの ファイルシステム UID と一致するファイルに対してだけである。 CAP_LEASE ケー
パビリティを持つプロセスは任意のファイルに対してリースを取得できる。
F_GETLEASE (void)
ファイルディスクリプタ fd に対して設定されているリースの種別を取得する。 F_RDLCK, F_WRLCK, F_UNLCK
のいずれかが返される。 F_RDLCK, F_WRLCK はそれぞれ、読み出しリース、書き込みリースが設定されている
ことを示し、 F_UNLCK はリースが何も設定されていないことを示す。 arg は無視される。
あるプロセス ("lease breaker") が F_SETLEASE で設定されたリースと矛 盾するような open(2) や truncate(2)
を実行した場合、 そのシステム コールはカーネルによって停止され、 カーネルは lease holder にシグナル (デ
フォルトでは SIGIO) を送って通知を行う。 lease holder はこのシグ ナルを受信したときにはきちんと対応すべき
である。 具体的には、別のプロセ スがそのファイルにアクセスするための準備として 必要な後片付け (例えば、
キャッシュされたバッファのフラッシュ) を すべて行ってから、そのファイル のリースの削除または格下げを行
う。リースを削除をするには、 arg に F_UNLCK を指定して F_SETLEASE を実行する。lease holder がファイル に
書き込みリースを保持していて、 lease breaker が読み出し用にそのファイ ルをオープンしている場合、 lease
holder が保持しているリースを読み出し リースに格下げすれば 十分である。これをするには、 arg に F_RDLCK を
指定して F_SETLEASE を実行する。
If the lease holder fails to downgrade or remove the lease within the number of seconds specified in
/proc/sys/fs/lease-break-time, then the kernel forcibly removes or downgrades the lease holder's lease.
いったん lease break が開始されると、 lease holder が自発的にそのリース の格下げか削除を行うか、lease
break timer の満了後にカーネルが強制的に リースの格下げか削除を行うまで、 F_GETLEASE は対象となるリースの
型を 返す (リースの型は F_RDLCK か F_UNLCK のどちらであり、lease breaker と互換性のある型となる)。
一度リースの削除か格下げが自発的もしくは強制的に行われると、 lease breaker がまだシステムコールを再開して
いない場合には、 カーネルが lease breaker のシステムコールの続行を許可する。
lease breaker が実行した open(2) や truncate(2) が停止中にシグナルハンドラにより中断された場合、 そのシ
ステムコールは EINTR エラーで失敗するが、上で述べた他の処理は そのまま行われる。 open(2) や truncate(2)
が停止中に lease breaker がシグナルにより kill された場合、 上で述べた他の処理はそのまま行われる。 lease
breaker が open(2) を呼ぶ際に O_NONBLOCK フラグを指定した場合、そのシステムコールは EWOULDBLOCK エラーで
直ちに失敗するが、上で述べた他の処理はそのまま行われる。
lease holder への通知に使われるデフォルトのシグナルは SIGIO だが、 fcntl() の F_SETSIG コマンドで変更す
ることができる。 F_SETSIG コマンドが実行され (SIGIO を指定された場合も含む)、 SA_SIGINFO フラグ付きでシグ
ナルハンドラが設定されている場合には、 ハンドラの第二引き数として siginfo_t 構造体が渡され、この引き数の
si_fd フィールドには別のプロセスがアクセスしたリース設定済みファイルの ディスクリプタが入っている (この機
能は複数のファイルに対してリースを設定する場合に有用である)。
ファイルやディレクトリの変更の通知 (dnotify)
F_NOTIFY (int)
(Linux 2.4 以降) fd で参照されるディレクトリか、その中にあるファイルに変更があった場合に 通知を行
う。どのイベントを通知するかは arg で指定する。 arg はビットマスクで、以下のビットの 0個以上の論理
和をとったものを指定する。
DN_ACCESS ファイルへのアクセスがあった (read, pread, readv)
DN_MODIFY ファイルの内容が変更された (write, pwrite, writev, truncate, ftruncate).
DN_CREATE ファイルが作成された (open, creat, mknod, mkdir, link, symlink, rename).
DN_DELETE ファイルが削除 (unlink) された (unlink, 別のディレクトリへの rename, rmdir)
DN_RENAME ディレクトリ内でのファイル名の変更があった (rename)
DN_ATTRIB ファイル属性が変更された (chown, chmod, utime[s])
(上記の定義を利用するには、どの ヘッダファイルをインクルードするより前に、 _GNU_SOURCE 機能検査マ
クロを定義しなければならない。)
ディレクトリの変更通知は通常「一回限り (one-shot)」であり、 アプリケーション側でその後さらに通知を
受信したい場合は 再登録しなければならない。 arg に DN_MULTISHOT が含まれていた場合には、 変更通知
は明示的に解除されるまで有効状態が継続する。
F_NOTIFY 要求は積算されていく。つまり、 arg で指定されたイベントがすでにモニタされている イベント
集合に加算される形になる。 すべてのイベントの通知を無効にするには、 arg に 0 を指定して F_NOTIFY
を呼び出す必要がある。
通知はシグナルの配送で行われる。 デフォルトのシグナルは SIGIO だが、 fcntl() の F_SETSIG コマンド
で変更することができる。 後者の場合には、 (SA_SIGINFO フラグ付きでシグナルハンドラが設定されている
場合には) ハンドラの第二引き数として siginfo_t 構造体が渡され、この構造体の si_fd フィールドには通
知の行われたファイルディスクリプタが入っている (この機能は複数のディレクトリに対して通知を設定する
場合に有用である)。
特に DN_MULTISHOT を使う場合は、通知にはリアルタイムシグナルを使うべきである。 それは、リアルタイ
ムシグナルを使うことで、複数の通知をキューに入れる ことができるからである。
注意: 新しくアプリケーションを書く際には、(カーネル 2.6.13 以降で利用可能となった) inotify インタ
フェースを使用すべきである。 inotify はファイルシステムイベントの通知を取得するための ずっと優れた
インタフェースである。 inotify(7) を参照。
パイプの容量の変更
F_SETPIPE_SZ (int; Linux 2.6.35 以降)
fd が参照するパイプの容量を少なくとも arg バイトに変更する。 非特権プロセスは、パイプの容量とし
て、 システムのページサイズと /proc/sys/fs/pipe-max-size で定義される 上限値 (proc(5) 参照) の間の
任意の値を設定できる。 パイプの容量をページサイズよりも小さな値に設定しようとした場合は、 暗黙のう
ちにページサイズに切り上げられる。 非特権プロセスがパイプの容量を /proc/sys/fs/pipe-max-size で定
義 された上限より大きな値に設定しようとした場合は、エラー EPERM が 発生する。特権プロセス
(CAP_SYS_RESOURCE ケーパビリティを持つ プロセス) はこの上限を上書きできる。 パイプにバッファを割り
当てる場合、実装側の都合に応じて、 カーネルは arg よりも大きな容量を割り当ててもよい。
F_GETPIPE_SZ 操作では実際に使用されている大きさが返される。 パイプの容量を現在データを格納するのに
使用されているバッファの サイズよりも小さくしようとした場合は、エラー EBUSY が発生する。
F_GETPIPE_SZ (void; Linux 2.6.35 以降)
fd が参照するパイプの容量を (関数の結果として) 返す。
返り値
成功した場合の返り値は操作の種類により違う:
F_DUPFD 新しいディスクリプタを返す。
F_GETFD ファイルディスクリプタフラグの値
F_GETFL ファイル状態フラグの値
F_GETLEASE
ファイルディスクリプタに対して保持されているリースの種別を返す。
F_GETOWN ディスクリプタの所有者を返す。
F_GETSIG 読み込みや書き出しが可能になった時に送られるシグナルの値、もしくは 伝統的な SIGIO 動作の場合には
ゼロを返す。
F_GETPIPE_SZ
パイプの容量。
他の全てのコマンド
0 を返す。
エラーの時は -1 が返され、 errno に適切な値が設定される。
エラー
EACCES か EAGAIN
他のプロセスが保持しているロックによって操作が禁止されている。
EAGAIN そのファイルは他のプロセスによってメモリマップされているため、 操作が禁止されている。
EBADF fd がオープンされたファイルディスクリプタでない。 あるいはコマンドが F_SETLK または F_SETLKW だっ
たが、対象のファイルディスクリプタのオープンモードが 必要となるロックの型にマッチしていない。
EDEADLK
指定された F_SETLKW コマンドを実行した場合にはデッドロックになることが検出された。
EFAULT lock が利用可能なアドレス空間の外部にある。
EINTR F_SETLKW コマンドがシグナルにより割り込まれた (signal(7) 参照)。 F_GETLK と F_SETLK の場合、ロッ
クを確認したり取得したりする前にシグナルによって割り込まれた。 これはたいていリモートのファイルを
ロックする場合 (例えば NFS 上でロックする場合) に起こる。 しかしローカルでも起こる場合がある。
EINVAL F_DUPFDで、 arg が負か、もしくは許される最大値よりも大きい。 F_SETSIG の場合、 arg が利用可能なシ
グナル番号ではない。
EMFILE F_DUPFDで、 プロセスがすでに最大数までファイルディスクリプタをオープンしている。
ENOLCK オープンされているロックの数が多過ぎて、ロックテーブルがいっぱいである。 または remote locking
protocol (例えば NFS 上のロック) が失敗した。
EPERM 追加専用属性が設定されたファイルの O_APPEND フラグをクリアしようと試みた。
準拠
SVr4, 4.3BSD, POSIX.1-2001. POSIX.1-2001 で規定されている操作は、 F_DUPFD, F_GETFD, F_SETFD, F_GETFL,
F_SETFL, F_GETLK, F_SETLK, F_SETLKW だけである。
F_GETOWN と F_SETOWN は POSIX.1-2001 で規定されている。 (これら定義するには、 _BSD_SOURCE を定義するか、
_XOPEN_SOURCE を 500 以上の値で定義するか、 _POSIX_C_SOURCE を 200809L 以上の値で定義すること。)
F_DUPFD_CLOEXEC は POSIX.1-2008 で規定されている。 (これら定義するには、 _POSIX_C_SOURCE を 200809L 以上
の値で定義するか、 _XOPEN_SOURCE を 700 以上の値で定義すること。)
F_GETOWN_EX, F_SETOWN_EX, F_SETPIPE_SZ, F_GETPIPE_SZ, F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE,
F_SETLEASE は Linux 固有である (これらの定義を有効にするには _GNU_SOURCE マクロを定義すること)。
注意
元々の Linux の fcntl() システムコールは (flock 構造体で) 大きな ファイルオフセットを扱えるように設計され
ていなかった。 その結果、Linux 2.4 で fcntl64() システムコールが追加された。 この新しいシステムコール
は、ファイルのロックに flock64 という別の 構造体を利用し、これに対応するコマンドとして F_GETLK64,
F_SETLK64, F_SETLKW64 を使用する。 しかし、 glibc を使うアプリケーションではこれらの詳細を無視することが
できる。 glibc の fcntl のラッパー関数は新しいシステムコールが 利用できる場合はそれを利用するようになって
いるからである。
エラーの際の返り値が dup2(2) と F_DUPFD では異なっている。
カーネル 2.0 以降では、 flock(2) と fcntl() が設定するロック種別の間に相互作用はない。
システムによっては、 struct flock に上記以外のフィールドがあるものもある (例えば l_sysid)。 はっきりと言
えることは、ロックを保持しているプロセスが別のマシンに存在 する場合には、 l_pid だけはあまり役にたたない
だろうということである。
バグ
F_SETFL
F_SETFL を使って、 フラグ O_DSYNC と O_SYNC の状態を変更することはできない。これらのフラグの状態を変更し
ようとした場合には、黙って無視される。
F_GETOWN
いくつかのアーキテクチャ (特に i386) における Linux システムコールの慣習 のため以下の制限が存在する。
F_GETOWN が返す (負の) プロセスグループID が -1 から -4095 の範囲に入った場合、 glibc はこの返り値をシス
テムコールでエラーが起こったと間違って解釈してしまう。 つまり、 fcntl() の返り値は -1 となり、 errno には
(正の) プロセスグループID が設定されることになる。Linux 固有の F_GETOWN_EX ではこの問題を回避できる。
glibc バージョン 2.11 以降では、glibc では F_GETOWN_EX を使って F_GETOWN を実装することで、カーネルの
F_GETOWN の問題を見えないようにしている。
F_SETOWN
Linux 2.4 以前では、非特権プロセスが F_SETOWN を使って、ソケットのファイルディスクリプタの所有者に 呼び出
し元以外のプロセス (やプロセスグループ) を指定すると 発生するバグがある。この場合、 呼び出し元が所有者と
して指定したプロセス (やプロセスグループ) に シグナルを送る許可を持っていたとしても、 fcntl() が -1 を返
し errno に EPERM を設定することがある。 このエラーが返ったにもかかわらず、ファイルディスクリプタの所有者
は設定され、シグナルはその所有者に送られる。
強制ロック (mandatory locking)
これまでの Linux の全てのバージョンにおける強制ロックの実装は、 競合条件下で強制ロックが不完全になるよう
な場合がある。 ロックと重なって実行された write(2) の呼び出しは強制ロックが獲得された後にもデータを変更
することができる。 ロックと重なって実行された read(2) の呼び出しは強制ロックが獲得された後になって行われ
たデータの変更を 検出することができる。 同様の競合条件が強制ロックと mmap(2) の間にも存在する。それゆ
え、強制ロックに頼るのはお薦めできない。
関連項目
dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7)
Linux カーネルソースの Documentation/filesystems/ ディレクトリ内の locks.txt, mandatory-locking.txt,
dnotify.txt (以前のカーネルでは、これらのファイルは Documentation/ ディレクトリ直下にあり、
mandatory-locking.txt は mandatory.txt という名前であった)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告
に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
Linux 2014-04-20 FCNTL(2)