.\" t .\" This manpage is Copyright (C) 1992 Drew Eckhardt; .\" and Copyright (C) 1993 Michael Haardt, Ian Jackson; .\" and Copyright (C) 1998 Jamie Lokier; .\" and Copyright (C) 2002-2010, 2014 Michael Kerrisk; .\" and Copyright (C) 2014 Jeff Layton .\" and Copyright (C) 2014 David Herrmann .\" .\" %%%LICENSE_START(VERBATIM) .\" Permission is granted to make and distribute verbatim copies of this .\" manual provided the copyright notice and this permission notice are .\" preserved on all copies. .\" .\" Permission is granted to copy and distribute modified versions of this .\" manual under the conditions for verbatim copying, provided that the .\" entire resulting derived work is distributed under the terms of a .\" permission notice identical to this one. .\" .\" Since the Linux kernel and libraries are constantly changing, this .\" manual page may be incorrect or out-of-date. The author(s) assume no .\" responsibility for errors or omissions, or for damages resulting from .\" the use of the information contained herein. The author(s) may not .\" have taken the same level of care in the production of this manual, .\" which is licensed free of charge, as they might when working .\" professionally. .\" .\" Formatted or processed versions of this manual, if unaccompanied by .\" the source, must acknowledge the copyright and authors of this work. .\" %%%LICENSE_END .\" .\" Modified 1993-07-24 by Rik Faith .\" Modified 1995-09-26 by Andries Brouwer .\" and again on 960413 and 980804 and 981223. .\" Modified 1998-12-11 by Jamie Lokier .\" Applied correction by Christian Ehrhardt - aeb, 990712 .\" Modified 2002-04-23 by Michael Kerrisk .\" Added note on F_SETFL and O_DIRECT .\" Complete rewrite + expansion of material on file locking .\" Incorporated description of F_NOTIFY, drawing on .\" Stephen Rothwell's notes in Documentation/dnotify.txt. .\" Added description of F_SETLEASE and F_GETLEASE .\" Corrected and polished, aeb, 020527. .\" Modified 2004-03-03 by Michael Kerrisk .\" Modified description of file leases: fixed some errors of detail .\" Replaced the term "lease contestant" by "lease breaker" .\" Modified, 27 May 2004, Michael Kerrisk .\" Added notes on capability requirements .\" Modified 2004-12-08, added O_NOATIME after note from Martin Pool .\" 2004-12-10, mtk, noted F_GETOWN bug after suggestion from aeb. .\" 2005-04-08 Jamie Lokier , mtk .\" Described behavior of F_SETOWN/F_SETSIG in .\" multithreaded processes, and generally cleaned .\" up the discussion of F_SETOWN. .\" 2005-05-20, Johannes Nicolai , .\" mtk: Noted F_SETOWN bug for socket file descriptor in Linux 2.4 .\" and earlier. Added text on permissions required to send signal. .\" 2009-09-30, Michael Kerrisk .\" Note obsolete F_SETOWN behavior with threads. .\" Document F_SETOWN_EX and F_GETOWN_EX .\" 2010-06-17, Michael Kerrisk .\" Document F_SETPIPE_SZ and F_GETPIPE_SZ. .\" 2014-07-08, David Herrmann .\" Document F_ADD_SEALS and F_GET_SEALS .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .\" .\" Japanese Version Copyright (c) 1996 Takeshi Ueno .\" and Copyright (c) 2005, 2006, 2008 Akihiro MOTOKI .\" Translated 1996-07-03, Takeshi Ueno .\" Modified 1998-09-10, HANATAKA Shinya .\" Modified 1999-08-14, HANATAKA Shinya .\" Updated & Modified 2001-04-03, Yuichi SATO .\" Updated & Modified 2005-03-15, Akihiro MOTOKI .\" Updated & Modified 2005-04-22, Akihiro MOTOKI .\" Updated & Modified 2005-10-14, Akihiro MOTOKI .\" Updated & Modified 2005-11-19, Akihiro MOTOKI, LDP v2.14 .\" Updated 2006-04-16, Akihiro MOTOKI, LDP v2.29 .\" Updated 2008-02-11, Akihiro MOTOKI, LDP v2.77 .\" Updated 2008-09-19, Akihiro MOTOKI, LDP v3.09 .\" Updated 2010-04-23, Akihiro MOTOKI, LDP v3.24 .\" Updated 2012-05-08, Akihiro MOTOKI .\" Updated 2013-03-26, Akihiro MOTOKI .\" .TH FCNTL 2 2015\-01\-22 Linux "Linux Programmer's Manual" .SH 名前 fcntl \- ファイルディスクリプターの操作を行う .SH 書式 .nf \fB#include \fP \fB#include \fP .sp \fBint fcntl(int \fP\fIfd\fP\fB, int \fP\fIcmd\fP\fB, ... /* \fP\fIarg\fP\fB */ );\fP .fi .SH 説明 \fBfcntl\fP() は、オープンされたファイルディスクリプター \fIfd\fP に関して下記の操作を行う。操作は \fIcmd\fP によって決まる: \fBfcntl\fP() はオプションとして第三引き数をとることができる。 第三引き数が必要 かどうかは \fIcmd\fP により決まる。必要な引き数の型は \fIcmd\fP 名の後ろの括弧内で 指定されている (ほとんどの場合、必要な型は \fIint\fP であり、この引き数を表すの に \fIarg\fP という名前を使っている)。引き数が必要ない場合には \fIvoid\fP が指定さ れている。 下記のいくつかの操作は特定のバージョンの Linux カーネルでのみサポートされている。 ホストカーネルが特定の操作をサポートしているかを確認する推奨の方法は、 \fBfcntl\fP() を所望の \fIcmd\fP 値で呼び出し、 \fBEINVAL\fP で失敗するかを検査することである。 \fBEINVAL\fP が返った場合、カーネルがこの値を認識していないことを示す。 .SS ファイルディスクリプターの複製 .TP \fBF_DUPFD\fP (\fIint\fP) 利用可能なファイルディスクリプターのうち、 \fIarg\fP 以上で最小のものを探し、 \fIfd\fP のコピーとする。これは別の形の \fBdup2\fP(2) である。 \fBdup2\fP(2) では指定されたディスクリプターが使われる点が違う。 .IP 成功すると、新しいディスクリプターが返される。 .IP 詳細は \fBdup\fP(2) を参照のこと。 .TP \fBF_DUPFD_CLOEXEC\fP (\fIint\fP; Linux 2.6.24 以降) \fBF_DUPFD\fP と同様だが、それに加えて複製されたディスクリプターに対して close\-on\-exec フラグをセットする。 このフラグを指定することで、プログラムは \fBFD_CLOEXEC\fP フラグをセットするために \fBfcntl\fP() の \fBF_SETFD\fP 操作を追加で行う必要がなくなる。 このフラグがなぜ有用かについては、 \fBopen\fP(2) の \fBO_CLOEXEC\fP の説明を参照のこと。 .SS ファイルディスクリプターフラグ 以下のコマンドを使って、ファイルディスクリプターに関連するフラグ を操作することができる。 現在のところ、定義されているフラグは一つだけである: \fBFD_CLOEXEC\fP (close\-on\-exec フラグ)。 \fBFD_CLOEXEC\fP ビットが 0 なら、ファイルディスクリプターは \fBexecve\fP(2) を行ってもオープンされたままだが、そうでない場合はクローズされる。 .TP \fBF_GETFD\fP (\fIvoid\fP) ファイルディスクリプターフラグを読み出す。 \fIarg\fP は無視される。 .TP \fBF_SETFD\fP (\fIint\fP) ファイルディスクリプターフラグに \fIarg\fP で指定した値を設定する。 .PP マルチスレッドプログラムでは、 \fBfcntl\fP() の \fBF_SETFD\fP を使って close\-on\-exec フラグを設定するのと同時に、 別のスレッドで \fBexecve\fP(2) と \fBfork\fP(2) を実行することは、競合条件次第では、 そのファイルディスクリプターが子プロセスで実行されるプログラムに意図せず見えてしまうという危険性がある。 詳細とこの問題への対処法については \fBopen\fP(2) の \fBO_CLOEXEC\fP フラグの議論を参照のこと。 .SS ファイル状態フラグ .\" or .\" .BR creat (2), オープンファイル記述 (open file description) には、 ファイル記述毎に設定される状態フラグがいくつかある。これらのフラグは \fBopen\fP(2) によって初期化され、 \fBfcntl\fP(2) により変更することもできる。これらは、 (\fBdup\fP(2), \fBfcntl\fP(F_DUPFD), \fBfork\fP(2) などで) 複製されたファイルディスクリプター同士は 同じオープンファイル記述を参照する。 そのため、 同じファイル状態フラグが共有される。 ファイル状態フラグとその意味は \fBopen\fP(2) で説明されている。 .TP \fBF_GETFL\fP (\fIvoid\fP) ファイルのアクセスモードとファイル状態フラグを取得する。 \fIarg\fP は無視される。 .TP \fBF_SETFL\fP (\fIint\fP) ファイル状態フラグに \fIarg\fP で指定された値を設定する。 \fIarg\fP のうち、ファイルのアクセスモード (\fBO_RDONLY\fP, \fBO_WRONLY\fP, \fBO_RDWR\fP) とファイル作成フラグ (すなわち \fBO_CREAT\fP, \fBO_EXCL\fP, \fBO_NOCTTY\fP, \fBO_TRUNC\fP) に関するビットは無視される。 Linux では、このコマンドで変更できるのは \fBO_APPEND\fP, \fBO_ASYNC\fP, \fBO_DIRECT\fP, \fBO_NOATIME\fP, \fBO_NONBLOCK\fP フラグだけである。フラグ \fBO_DSYNC\fP, \fBO_SYNC\fP を変更することはできない。下記の「バグ」を参照。 .SS アドバイザリーレコードロック Linux は昔からある (「プロセスに関連付けられる」) UNIX のレコードロックを実装している。 このレコードロックは POSIX で標準化されている。 Linux 固有のより良い動作を行うロックについては、下記のオープンファイル記述ロックの議論を参照のこと。 \fBF_SETLK\fP, \fBF_SETLKW\fP, \fBF_GETLK\fP は、レコードロックの獲得/解放/テストのために使用する (レコードロックは、バイト範囲ロック、ファイルセグメントロック、ファイル領域ロックとも呼ばれる)。 三番目の引き数 \fIlock\fP は、以下に示すフィールドを含む構造体へのポインターである (フィールドの順序は関係なく、構造体に他のフィールドがあってもよい)。 .in +4n .nf .sp 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 (set by F_GETLK and F_OFD_GETLK) */ ... }; .fi .in .P この構造体の \fIl_whence\fP, \fIl_start\fP, \fIl_len\fP フィールドで、ロックを行いたいバイト範囲を指定する。 ファイルの末尾より後ろのバイトをロックすることはできるが、 ファイルの先頭より前のバイトをロックすることはできない。 \fIl_start\fP はロックを行う領域の開始オフセットである。 その意味は \fIl_whence\fP により異なる: \fIl_whence\fP が \fBSEEK_SET\fP の場合はファイルの先頭からのオフセット、 \fIl_whence\fP が \fBSEEK_CUR\fP の場合は現在のファイルオフセットからのオフセット、 \fIl_whence\fP が \fBSEEK_END\fP の場合はファイルの末尾からのオフセットと解釈される。 後ろの2つの場合には、 ファイルの先頭より前にならない範囲で、 \fIl_start\fP に負の値を指定することができる。 \fIl_len\fP はロックしたいバイト数を示す。 \fIl_len\fP が正の場合、ロックされるバイト範囲は \fIl_start\fP 以上 \fIl_start\fP+\fIl_len\fP\-1 以下となる。 \fIl_len\fP に 0 を指定した場合は特別な意味を持つ: \fIl_whence\fP and \fIl_start\fP で指定される位置からファイルの末尾までの全てのバイトをロックする (ファイルがどんなに大きくなったとしてもファイルの末尾までロックする)。 POSIX.1\-2001 では、負の値の \fIl_len\fP をサポートする実装を認めている (必須ではない)。 \fIl_len\fP が負の場合、ロックされるバイト範囲は \fIl_start\fP+\fIl_len\fP 以上 \fIl_start\fP\-1 以下となる。 この動作はカーネル 2.4.21 以降および 2.5.49 以降の Linux で サポートされている。 \fIl_type\fP フィールドは、ファイルに対して読み出しロック (\fBF_RDLCK\fP) と書き込みロック (\fBF_WRLCK\fP) のどちらを 設定するかを指定する。 ファイルのある領域に対して、読み出しロック (共有ロック) を保持できる プロセス数に制限はないが、書き込みロック (排他ロック) を保持できる のは一つのプロセスだけである。排他ロックを設定すると、(共有ロックか 排他ロックにかかわらず) 他のロックは何も設定できない。 一つのプロセスは、ファイルのある領域に対して一種類のロックしか保持できない。 新規のロックがロックが設定されている領域に対して適用されると、既存のロック は新規のロックの種別に変換される (新規のロックで指定されたバイト範囲が既存ロックの範囲と一致する場合以外では、 変換の過程で既存のロックの分割、縮小、結合が行われることがある)。 .TP \fBF_SETLK\fP (\fIstruct flock *\fP) (\fIl_type\fP が \fBF_RDLCK\fP か \fBF_WRLCK\fP の場合は) ロックの獲得を、 (\fBF_UNLCK\fP の場合は) ロックの解放を、 \fIflock\fP 構造体のフィールド \fIl_whence\fP, \fIl_start\fP, \fIl_len\fP で指定された範囲のバイトに対して行う。 指定されたロックが他のプロセスが設定しているロックと衝突する場合は、 \-1 を返し、 \fIerrno\fP に \fBEACCES\fP か \fBEAGAIN\fP を設定する。 (この場合に返されるエラーは実装により異なる。 そのため、 POSIX では移植性が必要なアプリケーションでは、 これらの両方のエラーをチェックすることが必要としている。) .TP \fBF_SETLKW\fP (\fIstruct flock *\fP) \fBF_SETLK\fP と同様だが、こちらではそのファイルに対して衝突するロックが 適用されていた場合に、そのロックが解放されるのを待つ点が異なる。 待っている間にシグナルを受けた場合は、システムコールは中断され、 (シグナルハンドラーが戻った直後に) 返り値 \-1 を返す (また \fIerrno\fP に \fBEINTR\fP が設定される; \fBsignal\fP(7) 参照)。 .TP \fBF_GETLK\fP (\fIstruct flock *\fP) このコールの呼び出し時には、 \fIlock\fP にはそのファイルに適用しようとするロックに関する情報が入っている。 ロックを適用できる場合には、 \fBfcntl\fP() は実際にはロックを行わず、 構造体 \fIlock\fP の \fIl_type\fP フィールドに \fBF_UNLCK\fP を返し、 他のフィールドは変更しない。 違う種別のロックが (一つもしくは複数) 適用されていてロックを適用できないような場合には、 \fBfcntl\fP() は、 原因となったロックの一つについての詳細を、 \fIlock\fP のフィールド \fIl_type\fP, \fIl_whence\fP, \fIl_start\fP, \fIl_len\fP で返す。 衝突するロックが昔からある (プロセスに関連付けられる) レコードロックの場合、 \fIl_pid\fP フィールドにロックを保持しているプロセスの PID が設定される。 衝突するロックがオープンファイル記述ロックの場合、 \fIl_pid\fP に \-1 が設定される。 呼び出し元がその内容を参照した時点では、 返された情報はすでに古いものとなっている可能性がある点に注意すること。 .P 読み出しロックを適用するには、 \fIfd\fP は読み出し用にオープンされていなければならない。 書き込みロックを適用するには、 \fIfd\fP は書き込み用にオープンされていなければならない。 読み書き両方のロックを適用するには、読み書き両用で ファイルをオープンしなければならない。 \fBF_SETLKW\fP でロックを適用する際、 カーネルは\fIデッドロック\fPの検出を行う。 2 つ以上のプロセスが、 他のプロセスが保持するロックにより互いにブロックされるようなロック要求を行っているかを検査する。 例えば、 プロセス A があるファイルのバイト 100 に対して書き込みロックを保持していて、 プロセス B がバイト 200 に対して書き込みロックを保持しているとする。 各プロセスが \fBF_SETLKW\fP を使って他のプロセスによるすでにロックされているバイトをロックしようとすると、 デッドロック検出がない場合、 両方のプロセスが無限に停止することになる。 カーネルはこのようなデッドロックを検出すると、 停止していたロック要求の一つをエラー \fBEDEADLK\fP ですぐに失敗させる。 このエラーを受け取ったアプリケーションは、 必要なロックを再度獲得しようとする前に、 他のアプリケーションが実行できるように自分が保持するロックのいくつかを解放する必要がある。 3 つ以上のプロセスが関連する循環するデッドロックも検出される。 ただし、 カーネルのデッドロック検出アルゴリズムには制限がある点に注意すること。 「バグ」を参照。 ろコードロックは \fBF_UNLCK\fP で明示的に削除されるだけでなく、 そのプロセスが終了した際には自動的に解放される。 .P レコードのロックは \fBfork\fP(2) で作成された子プロセスには継承されないが、 \fBexecve\fP(2) の前後では保存される。 .P \fBstdio\fP(3) ではバッファーリングが行われるので、 stdio 関連の関数ではレコードのロックの使用は回避される; 代わりに \fBread\fP(2) や \fBwrite\fP(2) を使用すること。 上記で説明したレコードロックはプロセスと関連付けられる (以下で説明するオープンファイル記述ロックと異なる点である)。 そのため、 残念ながら以下のようなことが起こる。 .IP * 3 .\" (Additional file descriptors referring to the same file .\" may have been obtained by calls to .\" .BR open "(2), " dup "(2), " dup2 "(2), or " fcntl ().) プロセスがロックが適用されているファイルを参照しているファイルディスクリプターの「いずれか」をクローズした場合、 そのファイルに対するそのプロセスのすべてのロックが解放される。 この動作はまずい。 あるプロセスが \fI/etc/passwd\fP や \fI/etc/mtab\fP といったファイルにロックを適用しているときに、 あるライブラリ関数が何かの理由で同じファイルを open, read, close すると、そのファイルへのロックが失われることになる。 .IP * 1 つのプロセス内のスレッドはロックを共有する。 言い換えると、 マルチスレッドのプログラムで、 レコードロックを使って、 複数のスレッドが同時に 1 つのファイルの同じ領域にアクセスしないようにすることはできないということだ。 .PP オープンファイル記述ロックを使うとこれらの問題が解決できる。 .SS "オープンファイル記述ロック (非 POSIX)" オープンファイル記述ロックはバイト範囲に対するアドバイザリーロックで、 ほとんどの点で上述の昔からあるレコードロックと等価である。 このロック種別は Linux 固有であり、 Linux 3.15 以降で利用できる。 オープンファイル記述の説明は \fBopen\fP(2) を参照。 2 つのロック種別の主な違いは、 昔からあるレコードロックはプロセスに関連付けられるのに対して、 オープンファイル記述ロックはロックが獲得されるオープンファイル記述に関連付けられる点である。 この動作は \fBflock\fP(2) で獲得されるロックによく似ている。 結果として (昔からあるアドバイザリーレコードロックと違い)、 オープンファイル記述ロックは \fBfork\fP(2) (や \fBCLONE_FILES\fP 付きの \fBclone\fP(2)) の前後で継承され、 ファイルのクローズ時に解放されるのではなく、 オープンファイル記述の最後のクローズ時にのみ自動的に解放される。 .PP オープンファイル記述ロックは常に昔からあるレコードロックと競合する。 たとえ、 ロックが同じプロセスによって同じファイルディスクリプターに対して行われたとしてもである。 同じオープンファイル記述経由 (同じファイルディスクリプター経由や \fBfork\fP(2), \fBdup\fP(2), \fBfcntl\fP(2) \fBF_DUPFD\fP などで作成されたファイルディスクリプターの複製経由) で適用されたオープンファイル記述ロックは常に互換性がある。 つまり、 すでにロックされている領域に対して新しいロックが適用された場合、 既存のロックは新しいロック種別に変換される。 (上記で説明した通り、 このような変換の結果、 既存のロックの分割、 縮小、 結合が行われることがある。) 一方、 異なるオープンファイル記述経由で獲得されると、 オープンファイル記述ロックは互いに競合する。 したがって、 マルチスレッドプログラムのスレッドは、 各スレッドがそれぞれ自分で \fBopen\fP(2) を実行し、 得られたファイルディスクリプター経由でロックを適用することで、 オープンファイル記述ロックを使って一つのファイル領域えのアクセスを同期させることができる。 .PP 昔からあるレコードロックの場合と同様、 \fBfcntl\fP() の第 3 引き数 \fIlock\fP は \fIflock\fP 構造体へのポインターである。 昔からあるレコードロックと違い、 下記で説明するコマンドを使う際には、 この構造体のフィールド \fIl_pid\fP に 0 を設定しなければならない。 オープンファイル記述ロックで使用できるコマンドは、 昔からあるロックのコマンドと同じである。 .TP \fBF_OFD_SETLK\fP (\fIstruct flock *\fP) (\fIl_type\fP が \fBF_RDLCK\fP か \fBF_WRLCK\fP の場合は) オープンファイル記述のロックの獲得を、 (\fBF_UNLCK\fP の場合は) オープンファイル記述のロックの解放を、 \fIflock\fP 構造体のフィールド \fIl_whence\fP, \fIl_start\fP, \fIl_len\fP で指定された範囲のバイトに対して行う。 指定されたロックが他のプロセスが設定しているロックと衝突する場合は、 \-1 を返し、 \fIerrno\fP に \fBEAGAIN\fP を設定する。 .TP \fBF_OFD_SETLKW\fP (\fIstruct flock *\fP) \fBF_OFD_SETLK\fP と同様だが、こちらではそのファイルに対して衝突するロックが 適用されていた場合に、そのロックが解放されるのを待つ点が異なる。 待っている間にシグナルを受けた場合は、システムコールは中断され、 (シグナルハンドラーが戻った直後に) 返り値 \-1 を返す (また \fIerrno\fP に \fBEINTR\fP が設定される; \fBsignal\fP(7) 参照)。 .TP \fBF_OFD_GETLK\fP (\fIstruct flock *\fP) このコールの呼び出し時には、 \fIlock\fP にはそのファイルに適用しようとするロックに関する情報が入っている。 ロックを適用できる場合には、 \fBfcntl\fP() は実際にはロックを行わず、 構造体 \fIlock\fP の \fIl_type\fP フィールドで \fBF_UNLCK\fP を返し、 他のフィールドは変更しない。 違う種別のロックが (一つもしくは複数) 適用されていてロックを適用できないような場合には、 原因となったロックの一つについての詳細が \fIlock\fP で返される。 詳細は上記の \fBF_GETLK\fP を参照。 .PP .\" commit 57b65325fe34ec4c917bc4e555144b4a94d9e1f7 .\" 現在の実装では、 オープンファイル記述ロクではデッドロックの検出は行われない。 (これがプロセスと関連付けられるレコードロックとは異なる点である。 プロセスと関連付けられるレコードロックではカーネルはデッドロックの検出を行う。) .SS "強制ロック (mandatory locking)" \fI警告\fP: Linux の強制ロックの実装は信頼性に欠けるものである。 下記の「バグ」の節を参照のこと。 デフォルトでは、 昔からある (プロセスに関連付けられる) レコードロックも、 オープンファイル記述のろコードロックも、 アドバイザリーロックである。 アドバイザリーロックに強制力はなく、協調して動作するプロセス間でのみ有効である。 両方のタイプのロックも強制ロックにすることもできる。 強制ロックは全てのプロセスに対して効果がある。 あるプロセスが互換性のない強制ロックが適用されたファイル領域に対して (\fBread\fP(2) や \fBwrite\fP(2) により) 互換性のないアクセスを実行しようとした場合、 アクセスの結果は そのファイルのオープンファイル記述で \fBO_NONBLOCK\fP フラグが有効になっているかにより決まる。 \fBO_NONBLOCK\fP フラグが有効になっていないときは、ロックが削除されるか、 ロックがアクセスと互換性のあるモードに変換されるまで、 システムコールは停止 (block) される。 \fBO_NONBLOCK\fP フラグが有効になっているときは、システムコールはエラー \fBEAGAIN\fP で失敗する。 強制ロックを使用するためには、ロック対象のファイルが含まれるファイルシステム と、ロック対象のファイル自身の両方について、強制ロックが有効になっていなけれ ばならない。ファイルシステムについて強制ロックを有効にするには、 \fBmount\fP(8) に "\-o mand" オプションを渡すか、 \fBmount\fP(2) に \fBMS_MANDLOCK\fP フラグを指定する。ファイルについて強制ロックを有効にするには、 そのファイルのグループ実行許可 (group execute permission) を無効とし、 かつ set\-group\-ID 許可ビットを有効にする (\fBchmod\fP(1) と \fBchmod\fP(2) を参照)。 強制ロックは POSIX では規定されていない。 他のいくつかのシステムでも強制ロックはサポートされているが、 強制ロックをどのようにして有効にするかの詳細はシステムより異なる。 .SS シグナルの管理 \fBF_GETOWN\fP, \fBF_SETOWN\fP, \fBF_GETOWN_EX\fP, \fBF_SETOWN_EX\fP, \fBF_GETSIG\fP, \fBF_SETSIG\fP は、I/O が利用可能になったことを示すシグナルを管理するために使用される。 .TP \fBF_GETOWN\fP (\fIvoid\fP) ファイルディスクリプター \fIfd\fP のイベントに対するシグナル \fBSIGIO\fP および \fBSIGURG\fP を受けているプロセスのプロセスID かプロセスグループを (関数の結果として) 返す。 プロセスID は正の値として返される。 プロセスグループID は負の値として返される (下記のバグの章を参照)。 \fIarg\fP は無視される。 .TP \fBF_SETOWN\fP (\fIint\fP) ファイルディスクリプター \fIfd\fP のイベント発生を知らせるシグナル \fBSIGIO\fP や \fBSIGURG\fP を受けるプロセスの プロセス ID またはプロセスグループID を \fIarg\fP で指定された ID に設定する。 プロセスID は正の値として指定し、 プロセスグループID は負の値として指定する。 ほとんどの場合、呼び出し元プロセスは所有者として自分自身を指定する (つまり \fIarg\fP に \fBgetpid\fP(2) を指定する)。 .\" From glibc.info: \fBfcntl\fP() の \fBF_SETFL\fP コマンドを使用してファイルディスクリプターに \fBO_ASYNC\fP 状態フラグを設定した場合には、そのファイルディスクリプターへの 入出力が可能になる度に \fBSIGIO\fP シグナルが送られる。 \fBF_SETSIG\fP は \fBSIGIO\fP 以外の別のシグナルの配送を受けられるように するのにも使うことができる。 許可 (permission) のチェックで失敗した場合には、 シグナルは黙って捨てられる。 \fBF_SETOWN\fP により指定された所有者のプロセス (またはプロセスグループ) に シグナルを送る際には、 \fBkill\fP(2) に書かれているのと同じ許可のチェックが行われる。 このとき、シグナルを送信するプロセスは \fBF_SETOWN\fP を使ったプロセスである (但し、下記の「バグ」の章を参照のこと)。 .\" The following appears to be rubbish. It doesn't seem to .\" be true according to the kernel source, and I can write .\" a program that gets a terminal-generated SIGIO even though .\" it is not the foreground process group of the terminal. .\" -- MTK, 8 Apr 05 .\" .\" If the file descriptor .\" .I fd .\" refers to a terminal device, then SIGIO .\" signals are sent to the foreground process group of the terminal. ファイルディスクリプターがソケットを参照している場合は、 \fBF_SETOWN\fP を使用して、ソケットに帯域外 (out\-of\-band) データが届いた時に \fBSIGURG\fP シグナルを配送する相手を選択することもできる (\fBSIGURG\fP が送られた場合には \fBselect\fP(2) がソケットが「特別な状態」にあると報告することだろう)。 バージョン 2.6.11 以前の 2.6.x カーネルでは、以下に示す動作であった。 .RS .IP .\" The relevant place in the (2.6) kernel source is the .\" 'switch' in fs/fcntl.c::send_sigio_to_task() -- MTK, Apr 2005 .\" send_sigurg()/send_sigurg_to_task() bypasses .\" kill_fasync()/send_sigio()/send_sigio_to_task() .\" to directly call send_group_sig_info() .\" -- MTK, Apr 2005 (kernel 2.6.11) スレッドグループをサポートしているスレッドライブラリ (例えば NPTL) を 使って動作しているマルチスレッドプロセスで \fBF_SETSIG\fP に 0 以外の値を指定した場合、 \fBF_SETOWN\fP に正の値を渡すと、その意味が違ってくる: プロセス全体を示すプロセスID ではなく、プロセス内の特定の スレッドを示すスレッドID と解釈される。 したがって、 \fBF_SETSIG\fP を使う場合には、きちんと結果を受け取るには、 \fBF_SETOWN\fP に渡す値を \fBgetpid\fP(2) ではなく \fBgettid\fP(2) の返り値にする必要があるだろう。 (現状の Linux スレッド実装では、メインスレッドのスレッドID は そのスレッドのプロセスID と同じである。つまり、 シグナルスレッドのプログラムではこの場合 \fBgettid\fP(2) と \fBgetpid\fP(2) は全く同じように使うことができる。) ただし、注意すべき点として、この段落で述べたことは、 ソケットの帯域外データが届いたときに生成される \fBSIGURG\fP シグナルにはあてはまらない。 このシグナルは常にプロセスかプロセスグループに送られ、 送信先は \fBF_SETOWN\fP に渡された値にしたがって決められる。 .RE .IP 上記の動作は、Linux 2.6.12 で図らずも削除され、 元に戻されない予定である。 Linux 2.6.32 以降で、特定のスレッド宛にシグナル \fBSIGIO\fP と \fBSIGURG\fP を送るには \fBF_SETOWN_EX\fP を使うこと。 .TP \fBF_GETOWN_EX\fP (struct f_owner_ex *) (Linux 2.6.32 以降) 直前の \fBF_SETOWN_EX\fP 操作で定義された現在のファイルディスクリプターの所有者設定 を返す。情報は \fIarg\fP が指す構造体に格納されて返される。構造体は以下の通りである。 .nf .in +4n struct f_owner_ex { int type; pid_t pid; }; .in .fi \fItype\fP フィールドは、 \fBF_OWNER_TID ,\fP \fBF_OWNER_PID ,\fP \fBF_OWNER_PGRP\fP のいずれか一つの値となる。 \fIpid\fP フィールドは、スレッド ID、プロセス ID、プロセスグループ ID を 表す正の整数である。詳細は \fBF_SETOWN_EX\fP を参照。 .TP \fBF_SETOWN_EX\fP (struct f_owner_ex *) (Linux 2.6.32 以降) この操作は \fBF_SETOWN\fP と同様の処理を行う。 この操作を使うと、I/O が利用可能になったことを示すシグナルを、 特定のスレッド、プロセス、プロセスグループに送ることができる ようになる。 呼び出し元は、 \fIarg\fP 経由でシグナルの配送先を指定する。 \fIarg\fP は \fIf_owner_ex\fP 構造体へのポインターである。 \fItype\fP フィールドは以下のいずれかの値を取り、 この値により \fIpid\fP がどのように解釈されるかが規定される。 .RS .TP \fBF_OWNER_TID\fP スレッド ID が \fIpid\fP で指定された値のスレッドにそのシグナルを送る (スレッド ID は \fBclone\fP(2) や \fBgettid\fP(2) の呼び出しで返される値である)。 .TP \fBF_OWNER_PID\fP ID が \fIpid\fP で指定された値のプロセスにそのシグナルを送る。 .TP \fBF_OWNER_PGRP\fP ID が \fIpid\fP で指定された値のプロセスグループにそのシグナルを送る。 (\fBF_SETOWN\fP と異なり、プロセスグループ ID には正の値を指定する点に注意すること。) .RE .TP \fBF_GETSIG\fP (\fIvoid\fP) 入力や出力が可能になった場合に送るシグナルを (関数の結果として) 返す。 値ゼロは \fBSIGIO\fP を送ることを意味する。 (\fBSIGIO\fP を含む) 他の値はいずれも、 \fBSIGIO\fP の代わりに送るシグナル番号を表す。 後者の場合、シグナルハンドラーを \fBSA_SIGINFO\fP フラグ付きで設定すれば、ハンドラーで追加の情報を得ることができる。 \fIarg\fP は無視される。 .TP \fBF_SETSIG\fP (\fIint\fP) .\" .\" The following was true only up until 2.6.11: .\" .\" Additionally, passing a nonzero value to .\" .B F_SETSIG .\" changes the signal recipient from a whole process to a specific thread .\" within a process. .\" See the description of .\" .B F_SETOWN .\" for more details. 入力や出力が可能になった場合に送るシグナルを \fIarg\fP に指定された値に設定する。 値ゼロは \fBSIGIO\fP を送ることを意味する。 (\fBSIGIO\fP を含む) 他の値はいずれも、 \fBSIGIO\fP の代わりに送るシグナル番号を表す。 後者の場合、シグナルハンドラーを \fBSA_SIGINFO\fP フラグ付きで設定すれば、 ハンドラーで追加の情報を得ることができる。 \fBF_SETSIG\fP にゼロ以外の値を設定し、シグナルハンドラーに \fBSA_SIGINFO\fP フラグを設定すると、 (\fBsigaction\fP(2) を参照) I/O イベントに関する追加の情報が \fIsiginfo_t\fP 構造体でシグナルハンドラーへ渡される。 \fIsi_code\fP フィールドが示すシグナルの原因が \fBSI_SIGIO\fP である場合、 \fIsi_fd\fP フィールドにはイベントに対応するファイルディスクリプターが入っている。 それ以外の場合は、どのファイルディスクリプターが利用可能かを示す情報は ないので、どのファイルディスクリプターで I/O が可能かを判断するためには 通常の機構 (\fBselect\fP(2), \fBpoll\fP(2), \fBO_NONBLOCK\fP を設定した \fBread\fP(2) など) を使用しなければならない。 リアルタイムシグナル (値が \fBSIGRTMIN\fP 以上) を選択している場合は、 同じシグナル番号を持つ複数の I/O イベントがキューに入ることがある (キューに入れるかどうかは利用可能なメモリーに依存している)。 上記と同様、 \fBSA_SIGINFO\fP が設定されている場合、シグナルハンドラーのための追加の情報が得られる。 .\" See fs/fcntl.c::send_sigio_to_task() (2.4/2.6) sources -- MTK, Apr 05 以下の点に注意すること。 Linux では一つのプロセスに対してキューに入れられるリアルタイム シグナルの数に上限が設けられており (\fBgetrlimit\fP(2) と \fBsignal\fP(7) を参照)、この上限に達するとカーネルは \fBSIGIO\fP シグナルを配送する。この \fBSIGIO\fP シグナルは、指定されたスレッドではなくプロセス全体に送られる。 .PP これらの機構を使用することで、ほとんどの場合で \fBselect\fP(2) や \fBpoll\fP(2) を使用せずに完全な非同期 I/O を実装することができる。 .PP \fBO_ASYNC\fP の使用方法は BSD と Linux に特有である。 POSIX.1 で規定されている \fBF_GETOWN\fP と \fBF_SETOWN\fP の使用方法は、ソケットに対する \fBSIGURG\fP シグナルとの組み合わせだけである (POSIX は \fBSIGIO\fP シグナルは規定していない)。 \fBF_GETOWN_EX\fP, \fBF_SETOWN_EX\fP, \fBF_GETSIG\fP, \fBF_SETSIG\fP は Linux 固有である。POSIX には、同様のことを行うために、非同期 I/O と \fIaio_sigevent\fP 構造体がある。Linux では、GNU C ライブラリ (Glibc) の一部として これらも利用可能である。 .SS "リース (leases)" (Linix 2.4 以降で利用可能) \fBF_SETLEASE\fP は、 \fIfd\fP が参照するオープンファイル記述に対して新しいリースを設定するのに使用される。 \fBF_GETLEASE\fP は、 \fIfd\fP が参照するオープンファイル記述に対して設定されている 現在のリースを取得するのに使用される。 ファイルのリースにより、 あるプロセス ("lease breaker") がそのファイルディスクリプターが参照 しているファイルに対して \fBopen\fP(2) や \fBtruncate\fP(2) を行おうとした際に、リースを保持しているプロセス ("lease holder") へ (シグナルの配送による) 通知が行われるという機構が提供される。 .TP \fBF_SETLEASE\fP (\fIint\fP) \fIarg\fP の内容に基いてファイルのリースの設定、削除を行う。整数 \fIarg\fP には以下の値が指定できる: .RS .TP \fBF_RDLCK\fP .\" The following became true in kernel 2.6.10: .\" See the man-pages-2.09 Changelog for further info. 読み出しリースを取得する。これにより、 そのファイルが書き込み用にオープンされたり、ファイルが切り詰められた場合に、 呼び出し元のプロセスに通知が行われるようになる。 読み出しリースを設定できるのは、読み出し専用でオープンされている ファイルディスクリプターに対してのみである。 .TP \fBF_WRLCK\fP 書き込みリースを取得する。これにより、 (読み出し用か書き込み用にかかわらず) そのファイルがオープンされたり、 ファイルが切り詰められた場合に、呼び出し元のプロセスに通知が行われるようになる。 書き込みリースは、そのファイルに対するオープンされたファイルディスクリプターが 他にない場合にのみ設定できる。 .TP \fBF_UNLCK\fP そのファイルからリースを削除する。 .RE .P リースはオープンファイル記述に対して関連付けられる (\fBopen\fP(2) 参照)。 つまり、 (\fBfork\fP(2) や \fBdup\fP(2) などにより作成された) ファイルディスクリプターの複製は同じリースを参照し、 複製も含めたどのファイルディスクリプターを使ってもこのリースを変更したり 解放したりできる。 また、これらのファイルディスクリプターのいずれかに対して \fBF_UNLCK\fP 操作が明示的に実行された場合や、すべてのファイルディスクリプターが 閉じられた場合にも、リースは解放される。 .P リースの取得は通常のファイル (regular file) に対してのみ可能である。 非特権プロセスがリースを取得できるのは、UID (所有者) がプロセスの ファイルシステム UID と一致するファイルに対してだけである。 \fBCAP_LEASE\fP ケーパビリティを持つプロセスは任意のファイルに対してリースを取得できる。 .TP \fBF_GETLEASE\fP (\fIvoid\fP) ファイルディスクリプター \fIfd\fP に対して設定されているリースの種別を取得する。 \fBF_RDLCK\fP, \fBF_WRLCK\fP, \fBF_UNLCK\fP のいずれかが返される。 \fBF_RDLCK\fP, \fBF_WRLCK\fP はそれぞれ、読み出しリース、書き込みリースが設定されていることを示し、 \fBF_UNLCK\fP はリースが何も設定されていないことを示す。 \fIarg\fP は無視される。 .PP あるプロセス ("lease breaker") が \fBF_SETLEASE\fP で設定されたリースと矛 盾するような \fBopen\fP(2) や \fBtruncate\fP(2) を実行した場合、 そのシステム コールはカーネルによって停止され、 カーネルは lease holder にシグナル (デフォルトでは \fBSIGIO\fP) を送って通知を行う。 lease holder はこのシグ ナルを受信したときにはきちんと対応すべきである。 具体的には、別のプロセ スがそのファイルにアクセスするための準備として 必要な後片付け (例えば、 キャッシュされたバッファーのフラッシュ) を すべて行ってから、そのファイル のリースの削除または格下げを行う。リースを削除をするには、 \fIarg\fP に \fBF_UNLCK\fP を指定して \fBF_SETLEASE\fP を実行する。lease holder がファイル に書き込みリースを保持していて、 lease breaker が読み出し用にそのファイ ルをオープンしている場合、 lease holder が保持しているリースを読み出し リースに格下げすれば 十分である。これをするには、 \fIarg\fP に \fBF_RDLCK\fP を指定して \fBF_SETLEASE\fP を実行する。 If the lease holder fails to downgrade or remove the lease within the number of seconds specified in \fI/proc/sys/fs/lease\-break\-time\fP, then the kernel forcibly removes or downgrades the lease holder's lease. いったん lease break が開始されると、 lease holder が自発的にそのリース の格下げか削除を行うか、lease break timer の満了後にカーネルが強制的に リースの格下げか削除を行うまで、 \fBF_GETLEASE\fP は対象となるリースの型を 返す (リースの型は \fBF_RDLCK\fP か \fBF_UNLCK\fP のどちらであり、lease breaker と互換性のある型となる)。 一度リースの削除か格下げが自発的もしくは強制的に行われると、 lease breaker がまだシステムコールを再開していない場合には、 カーネルが lease breaker のシステムコールの続行を許可する。 lease breaker が実行した \fBopen\fP(2) や \fBtruncate\fP(2) が停止中にシグナルハンドラーにより中断された場合、 そのシステムコールは \fBEINTR\fP エラーで失敗するが、上で述べた他の処理は そのまま行われる。 \fBopen\fP(2) や \fBtruncate\fP(2) が停止中に lease breaker がシグナルにより kill された場合、 上で述べた他の処理はそのまま行われる。 lease breaker が \fBopen\fP(2) を呼ぶ際に \fBO_NONBLOCK\fP フラグを指定した場合、そのシステムコールは \fBEWOULDBLOCK\fP エラーで直ちに失敗するが、上で述べた他の処理はそのまま行われる。 lease holder への通知に使われるデフォルトのシグナルは \fBSIGIO\fP だが、 \fBfcntl\fP() の \fBF_SETSIG\fP コマンドで変更することができる。 \fBF_SETSIG\fP コマンドが実行され (\fBSIGIO\fP を指定された場合も含む)、 \fBSA_SIGINFO\fP フラグ付きでシグナルハンドラーが設定されている場合には、 ハンドラーの第二引き数として \fIsiginfo_t\fP 構造体が渡され、この引き数の \fIsi_fd\fP フィールドには別のプロセスがアクセスしたリース設定済みファイルの ディスクリプターが入っている (この機能は複数のファイルに対してリースを設定する場合に有用である)。 .SS "ファイルやディレクトリの変更の通知 (dnotify)" .TP \fBF_NOTIFY\fP (\fIint\fP) (Linux 2.4 以降) \fIfd\fP で参照されるディレクトリか、その中にあるファイルに変更があった場合に 通知を行う。どのイベントを通知するかは \fIarg\fP で指定する。 \fIarg\fP はビットマスクで、以下のビットの 0個以上の論理和をとったものを指定する。 .RS .sp .PD 0 .TP 12 \fBDN_ACCESS\fP ファイルへのアクセスがあった (\fBread\fP(2), \fBpread\fP(2), \fBreadv\fP(2) や同様のシステムコール) .TP \fBDN_MODIFY\fP ファイルの内容が変更された (\fBwrite\fP(2), \fBpwrite\fP(2), \fBwritev\fP(2), \fBtruncate\fP(2), \fBftruncate\fP(2) や同様のシステムコール) .TP \fBDN_CREATE\fP ファイルが作成された (\fBopen\fP(2), \fBcreat\fP(2), \fBmknod\fP(2), \fBmkdir\fP(2), " "\fBlink\fP(2), \fBsymlink\fP(2), このディレクトリへの \fBrename\fP(2)) .TP \fBDN_DELETE\fP ファイルが削除 (unlink) された (\fBunlink\fP(2), 別のディレクトリへの \fBrename\fP(2), \fBrmdir\fP(2)) .TP \fBDN_RENAME\fP ディレクトリ内でのファイル名の変更があった (\fBrename\fP(2)) .TP \fBDN_ATTRIB\fP ファイル属性が変更された (\fBchown\fP(2), \fBchmod\fP(2), \fButime\fP(2), \fButimensat\fP(2) や同様のシステムコール) .PD .RE .IP (上記の定義を利用するには、\fIどの\fP ヘッダーファイルをインクルードするより前に、 \fB_GNU_SOURCE\fP 機能検査マクロを定義しなければならない。) ディレクトリの変更通知は通常「一回限り (one\-shot)」であり、 アプリケーション側でその後さらに通知を受信したい場合は 再登録しなければならない。 \fIarg\fP に \fBDN_MULTISHOT\fP が含まれていた場合には、 変更通知は明示的に解除されるまで有効状態が継続する。 .\" The following does seem a poor API-design choice... \fBF_NOTIFY\fP 要求は積算されていく。つまり、 \fIarg\fP で指定されたイベントがすでにモニタされている イベント集合に加算される形になる。 すべてのイベントの通知を無効にするには、 \fIarg\fP に 0 を指定して \fBF_NOTIFY\fP を呼び出す必要がある。 通知はシグナルの配送で行われる。 デフォルトのシグナルは \fBSIGIO\fP だが、 \fBfcntl\fP() の \fBF_SETSIG\fP コマンドで変更することができる。 (\fBSIGIO\fP はキューイングされない標準のシグナルの一つである点に注意。 リアルタイムシグナルを使うように変更すると、 複数の通知がそのプロセス宛のキューに入ることがあることを意味する。) 後者の場合には、 (\fBSA_SIGINFO\fP フラグ付きでシグナルハンドラーが設定されている場合には) ハンドラーの第二引き数として \fIsiginfo_t\fP 構造体が渡され、この構造体の \fIsi_fd\fP フィールドには通知の行われたファイルディスクリプターが入っている (この機能は複数のディレクトリに対して通知を設定する場合に有用である)。 特に \fBDN_MULTISHOT\fP を使う場合は、通知にはリアルタイムシグナルを使うべきである。 それは、リアルタイムシグナルを使うことで、複数の通知をキューに入れる ことができるからである。 \fB注意:\fP 新しくアプリケーションを書く際には、(カーネル 2.6.13 以降で利用可能となった) \fIinotify\fP インターフェースを使用すべきである。 \fIinotify\fP はファイルシステムイベントの通知を取得するための ずっと優れたインターフェースである。 \fBinotify\fP(7) を参照。 .SS パイプの容量の変更 .TP \fBF_SETPIPE_SZ\fP (\fIint\fP; Linux 2.6.35 以降) \fIfd\fP が参照するパイプの容量を少なくとも \fIarg\fP バイトに変更する。 非特権プロセスは、パイプの容量として、 システムのページサイズと \fI/proc/sys/fs/pipe\-max\-size\fP で定義される 上限値 (\fBproc\fP(5) 参照) の間の任意の値を設定できる。 パイプの容量をページサイズよりも小さな値に設定しようとした場合は、 暗黙のうちにページサイズに切り上げられる。 非特権プロセスがパイプの容量を \fI/proc/sys/fs/pipe\-max\-size\fP で定義 された上限より大きな値に設定しようとした場合は、エラー \fBEPERM\fP が 発生する。特権プロセス (\fBCAP_SYS_RESOURCE\fP ケーパビリティを持つ プロセス) はこの上限を上書きできる。 パイプにバッファーを割り当てる場合、実装側の都合に応じて、 カーネルは \fIarg\fP よりも大きな容量を割り当ててもよい。 実際に設定された大きさが関数の返り値として返される。 パイプの容量を現在データを格納するのに使用されているバッファーの サイズよりも小さくしようとした場合は、エラー \fBEBUSY\fP が発生する。 .TP \fBF_GETPIPE_SZ\fP (\fIvoid\fP; Linux 2.6.35 以降) .\" \fIfd\fP が参照するパイプの容量を (関数の結果として) 返す。 .SS "File Sealing" file seal は指定されたファイルで許可される操作の集合を制限する。 ファイルに設定される seal 毎に対応する操作の集合が規定されており、 それ以降のそのファイルに対する対応する操作は \fBEPERM\fP で失敗する。 このようなファイルは sealed (seal が適用されている) と呼ばれる。 デフォルトの seal の集合は、適用されるファイルやファイルシステムに依存する。 file seal の概要、 その目的、 サンプルコードについては \fBmemfd_create\fP(2) を参照。 現在のところ \fItmpfs\fP ファイルシステムだけが sealing をサポートしている。 他のファイルシステムでは、 seal に関連する \fBfcntl\fP(2) の操作はすべて \fBEINVAL\fP を返す。 seal は inode の属性である。 したがって、 同じ inode を参照するすべてのオープンされたファイルディスクリプターは、 同じ seal の集合を共有する。 さらに、 seal は削除することはできず、 追加のみ可能である。 .TP \fBF_ADD_SEALS\fP (\fIint\fP; Linux 3.17 以降) ビットマスク引き数 \fIarg\fP で指定された seal を、 ファイルディスクリプター \fIfd\fP が参照する inode の seal の集合に追加する。 一度追加した seal を削除することはできない。 この呼び出しが成功すると、 seal はただちにカーネルにより適用される。 現在の seal の集合に \fBF_SEAL_SEAL\fP (下記参照) が含まれている場合、 この呼び出しは \fBEPERM\fP で拒否される。 すでに設定されている seal を追加した場合、 \fBF_SEAL_SEAL\fP がまだ設定されていない場合は no\-op (何もしない) となる。 seal を設定するには、 ファイルディスクリプター \fIfd\fP が書き込み可能でなければならない。 .TP \fBF_GET_SEALS\fP (\fIvoid\fP; Linux 3.17 以降) (関数の結果として) \fIfd\fP が参照する inode の seal の現在の集合を返す。 seal が何も設定されていない場合、 0 が返される。 ファイルが sealing をサポートしていない場合、 \-1 が返され、 \fIerrno\fP に \fBEINVAL\fP が設定される。 .PP 以下の seal が利用できる。 .TP \fBF_SEAL_SEAL\fP この seal が設定されると、 これ以降の \fBF_ADD_SEALS\fP を指定した \fBfcntl\fP(2) の呼び出しはすべて \fBEPERM\fP で失敗する。 したがって、 この seal を設定すると seal の集合自身の変更を防止できる。 ファイルの最初の seal の集合に \fBF_SEAL_SEAL\fP が含まれていた場合、 結果的に seal の集合が定数になりロックされることになる。 .TP \fBF_SEAL_SHRINK\fP この seal が設定されると、 設定されたファイルのサイズを小さくできなくなる。 この seal は \fBopen\fP(2) の \fBO_TRUNC\fP フラグに影響する。 \fBtruncate\fP(2) と \fBftruncate\fP(2) についても同様である。 対象のファイルのサイズを小さくしようとした場合、 これらの呼び出しは \fBEPERM\fP で失敗する。 ファイルサイズを増やすことはこの場合でも可能である。 .TP \fBF_SEAL_GROW\fP この seal が設定されると、 設定されたファイルのサイズを増やせなくなる。 この seal はファイルの末尾を超えての \fBwrite\fP(2) や \fBtruncate\fP(2), \fBftruncate\fP(2), \fBfallocate\fP(2) に影響する。 対象のファイルのサイズを大きくしようとした場合、 これらの呼び出しは \fBEPERM\fP で失敗する。 ファイルサイズが変わらない場合、 小さくなる場合は、 これらの呼び出しはそのまま動作する。 .TP \fBF_SEAL_WRITE\fP .\" One or more other seals are typically used with F_SEAL_WRITE .\" because, given a file with the F_SEAL_WRITE seal set, then, .\" while it would no longer be possinle to (say) write zeros into .\" the last 100 bytes of a file, it would still be possible .\" to (say) shrink the file by 100 bytes using ftruncate(), and .\" then increase the file size by 100 bytes, which would have .\" the effect of replacing the last hundred bytes by zeros. .\" この seal が設定されていると、 ファイルの内容を変更できない。 ファイルのサイズを縮小したり伸張したりすることは可能で許可されている。 したがって、 この seal は通常は他の seal のいずれかと組み合わせて使用される。 この seal は \fBwrite\fP(2) と \fBfallocate\fP(2) (\fBFALLOC_FL_PUNCH_HOLE\fP フラグとの組み合わせの場合のみ) に影響する。 この seal が設定されると、 これらの呼び出しは \fBEPERM\fP で失敗する。 また、 \fBmmap\fP(2) による新しい書き込み可能な共有メモリーマッピングの作成も \fBEPERM\fP で失敗する。 \fBfcntl\fP(2) の \fBF_ADD_SEALS\fP で \fBF_SEAL_WRITE\fP を設定しようとした場合、 書き込み可能な共有マッピングが存在すると \fBEBUSY\fP で失敗する。 このようなマッピングは、 この seal を追加する前にアンマップしなければならない。 また、 ファイルに対して処理待ちの非同期 I/O 操作 (\fBio_submit\fP(2) がある場合、 処理されていない書き込みは破棄される。 .SH 返り値 成功した場合の返り値は操作の種類により違う: .TP 0.9i \fBF_DUPFD\fP 新しいディスクリプターを返す。 .TP \fBF_GETFD\fP ファイルディスクリプターフラグの値 .TP \fBF_GETFL\fP ファイル状態フラグの値 .TP \fBF_GETLEASE\fP ファイルディスクリプターに対して保持されているリースの種別を返す。 .TP \fBF_GETOWN\fP ディスクリプターの所有者を返す。 .TP \fBF_GETSIG\fP 読み込みや書き出しが可能になった時に送られるシグナルの値、もしくは 伝統的な \fBSIGIO\fP 動作の場合にはゼロを返す。 .TP \fBF_GETPIPE_SZ\fP, \fBF_SETPIPE_SZ\fP パイプの容量。 .TP \fBF_GET_SEALS\fP \fIfd\fP が参照する inode に設定されている seal を示すビットマスク。 .TP 他の全てのコマンド 0 を返す。 .PP エラーの時は \-1 が返され、 \fIerrno\fP に適切な値が設定される。 .SH エラー .TP \fBEACCES\fP か \fBEAGAIN\fP 他のプロセスが保持しているロックによって操作が禁止されている。 .TP \fBEAGAIN\fP そのファイルは他のプロセスによってメモリーマップされているため、 操作が禁止されている。 .TP \fBEBADF\fP \fIfd\fP がオープンされたファイルディスクリプターではない。 .TP \fBEBADF\fP \fIcmd\fP が \fBF_SETLK\fP または \fBF_SETLKW\fP だったが、対象のファイルディスクリプターのオープンモードが 必要となるロックの型にマッチしていない。 .TP \fBEBUSY\fP \fIcmd\fP が \fBF_SETPIPE_SZ\fP で、 \fIarg\fP で指定されたパイプの新しい容量がパイプが、 現在パイプにあるデータを格納するのに使用されているバッファー容量よりも小さい。 .TP \fBEBUSY\fP \fIcmd\fP が \fBF_ADD_SEALS\fP で、 \fIarg\fP に \fBF_SEAL_WRITE\fP が含まれており、 \fIfd\fP が参照するファイルに対する書き込み可能な共有マッピングが存在する。 .TP \fBEDEADLK\fP 指定された \fBF_SETLKW\fP コマンドを実行した場合にはデッドロックになることが検出された。 .TP \fBEFAULT\fP \fIlock\fP が利用可能なアドレス空間の外部にある。 .TP \fBEINTR\fP \fIcmd\fP が \fBF_SETLKW\fP か \fBF_OFD_SETLKW\fP で、 操作がシグナルにより割り込まれた。 \fBsignal\fP(7) 参照。 .TP \fBEINTR\fP \fIcmd\fP が \fBF_GETLK\fP, \fBF_SETLK\fP, \fBF_OFD_GETLK\fP, \fBF_OFD_SETLK\fP で、 操作がシグナルにより割り込まれた (\fBsignal\fP(7) 参照)。 \fBF_GETLK\fP と \fBF_SETLK\fP の場合、ロックを確認したり取得したりする前にシグナルによって割り込まれた。 これはたいていリモートのファイルをロックする場合 (例えば NFS 上でロックする場合) に起こる。 しかしローカルでも起こる場合がある。 .TP \fBEINVAL\fP カーネルが認識しない値が \fIcmd\fP で指定された。 .TP \fBEINVAL\fP \fIcmd\fP が \fBF_ADD_SEALS\fP で、 \fIarg\fP に認識できない seal を示すビットが含まれている。 .TP \fBEINVAL\fP \fIcmd\fP が \fBF_ADD_SEALS\fP か \fBF_GET_SEALS\fP で、 \fIfd\fP が参照している inode が格納されているファイルシステムが sealing をサポートしていない。 .TP \fBEINVAL\fP \fIcmd\fP が \fBF_DUPFD\fP で、 \fIarg\fP が負か、もしくは許される最大値よりも大きい (\fBgetrlimit\fP(2) の \fBRLIMIT_NOFILE\fP の議論を参照)。 .TP \fBEINVAL\fP \fIcmd\fP が \fBF_SETSIG\fP で、 \fIarg\fP が許可されたシグナル番号ではない。 .TP \fBEINVAL\fP \fIcmd\fP が \fBF_OFD_SETLK\fP, \fBF_OFD_SETLKW\fP, \fBF_OFD_GETLK\fP のいずれかで、 \fIl_pid\fP に 0 が指定されなかった。 .TP \fBEMFILE\fP \fIcmd\fP が \fBF_DUPFD\fPで、 プロセスがすでに最大数までファイルディスクリプターをオープンしている。 .TP \fBENOLCK\fP オープンされているロックの数が多過ぎて、ロックテーブルがいっぱいである。 または remote locking protocol (例えば NFS 上のロック) が失敗した。 .TP \fBENOTDIR\fP \fBF_NOTIFY\fP が \fIcmd\fP に指定されたが、 \fIfd\fP がディレクトリを参照していない。 .TP \fBEPERM\fP 追加専用属性が設定されたファイルの \fBO_APPEND\fP フラグをクリアしようと試みた。 .TP \fBEPERM\fP \fIcmd\fP が \fBF_ADD_SEALS\fP だが、 \fIfd\fP が書き込み用にオープンされていないか、 ファイルの現在の seal の集合にすでに \fBF_SEAL_SEAL\fP が含まれている。 .SH 準拠 SVr4, 4.3BSD, POSIX.1\-2001. POSIX.1\-2001 で規定されている操作は、 \fBF_DUPFD\fP, \fBF_GETFD\fP, \fBF_SETFD\fP, \fBF_GETFL\fP, \fBF_SETFL\fP, \fBF_GETLK\fP, \fBF_SETLK\fP, \fBF_SETLKW\fP だけである。 \fBF_GETOWN\fP と \fBF_SETOWN\fP は POSIX.1\-2001 で規定されている。 (これら定義するには、 \fB_BSD_SOURCE\fP を定義するか、 \fB_XOPEN_SOURCE\fP を 500 以上の値で定義するか、 \fB_POSIX_C_SOURCE\fP を 200809L 以上の値で定義するか、 のいずれが必要である。) \fBF_DUPFD_CLOEXEC\fP は POSIX.1\-2008 で規定されている。 (これら定義するには、 \fB_POSIX_C_SOURCE\fP を 200809L 以上の値で定義するか、 \fB_XOPEN_SOURCE\fP を 700 以上の値で定義すること。) .\" .PP .\" SVr4 documents additional EIO, ENOLINK and EOVERFLOW error conditions. \fBF_GETOWN_EX\fP, \fBF_SETOWN_EX\fP, \fBF_SETPIPE_SZ\fP, \fBF_GETPIPE_SZ\fP, \fBF_GETSIG\fP, \fBF_SETSIG\fP, \fBF_NOTIFY\fP, \fBF_GETLEASE\fP, \fBF_SETLEASE\fP は Linux 固有である (これらの定義を有効にするには \fB_GNU_SOURCE\fP マクロを定義すること)。 \fBF_OFD_SETLK\fP, \fBF_OFD_SETLKW\fP, \fBF_OFD_GETLK\fP は Linux 固有だが (これらの定義を得るには \fB_GNU_SOURCE\fP を定義しなければならない)、 POSIX.1 の次のバージョンに含めようという活動が進められている。 .\" FIXME . Once glibc adds support, add a note about FTM requirements \fBF_ADD_SEALS\fP と \fBF_GET_SEALS\fP は Linux 固有である。 .SH 注意 .\" エラーの際の返り値が \fBdup2\fP(2) と \fBF_DUPFD\fP では異なっている。 .SS ファイルロック 元々の Linux の \fBfcntl\fP() システムコールは (\fIflock\fP 構造体で) 大きな ファイルオフセットを扱えるように設計されていなかった。 その結果、Linux 2.4 で \fBfcntl64\fP() システムコールが追加された。 この新しいシステムコールは、ファイルのロックに \fIflock64\fP という別の 構造体を利用し、これに対応するコマンドとして \fBF_GETLK64\fP, \fBF_SETLK64\fP, \fBF_SETLKW64\fP を使用する。 しかし、 glibc を使うアプリケーションではこれらの詳細を無視することが できる。 glibc の \fBfcntl\fP のラッパー関数は新しいシステムコールが 利用できる場合はそれを利用するようになっているからである。 エラーの際の返り値が \fBdup2\fP(2) と \fBF_DUPFD\fP では異なっている。 .SS レコードロック カーネル 2.0 以降では、 \fBflock\fP(2) と \fBfcntl\fP() が設定するロック種別の間に相互作用はない。 .\" e.g., Solaris 8 documents this field in fcntl(2), and Irix 6.5 .\" documents it in fcntl(5). mtk, May 2007 .\" Also, FreeBSD documents it (Apr 2014). システムによっては、 \fIstruct flock\fP に上記以外のフィールドがあるものもある (例えば \fIl_sysid\fP)。 はっきりと言えることは、ロックを保持しているプロセスが別のマシンに存在 する場合には、 \fIl_pid\fP だけはあまり役にたたないだろうということである。 元々の Linux の \fBfcntl\fP() システムコールは (\fIflock\fP 構造体で) 大きな ファイルオフセットを扱えるように設計されていなかった。 その結果、Linux 2.4 で \fBfcntl64\fP() システムコールが追加された。 この新しいシステムコールは、ファイルのロックに \fIflock64\fP という別の 構造体を利用し、これに対応するコマンドとして \fBF_GETLK64\fP, \fBF_SETLK64\fP, \fBF_SETLKW64\fP を使用する。 しかし、 glibc を使うアプリケーションではこれらの詳細を無視することが できる。 glibc の \fBfcntl\fP のラッパー関数は新しいシステムコールが 利用できる場合はそれを利用するようになっているからである。 .SS "レコードロックと NFS" .\" .\" Neil Brown: With NFSv3 the failure mode is the reverse. If .\" the server loses contact with a client then any lock stays in place .\" indefinitely ("why can't I read my mail"... I remember it well). .\" .\" .\" Jeff Layton: .\" Note that this is not a firm timeout. The server runs a job .\" periodically to clean out expired stateful objects, and it's likely .\" that there is some time (maybe even up to another whole lease period) .\" between when the timeout expires and the job actually runs. If the .\" client gets a RENEW in there within that window, its lease will be .\" renewed and its state preserved. .\" Linux 3.12 より前では、 NFSv4 クライアントが一定時間サーバーと通信がなかった場合 (90 秒間通信がない場合と定義されている)、 クライアントが気付かずにロックを失い再獲得する場合がある。 (通信がなくなったみなす時間は NFSv4 leastime と呼ばれる。 Linux NFS サーバーでは、 この値は \fI/proc/fs/nfsd/nfsv4leasetime\fP を見て決定される。 このファイルの値の単位は秒であり、 このファイルのデフォルト値は 90 である。) この状況では潜在的にデータ破壊が起こる危険性がある。 通信がなかった間に他のプロセスがロックを獲得しファイル入出力を行う場合があるからである。 .\" commit ef1820f9be27b6ad158f433ab38002ab8131db4d .\" commit f6de7a39c181dfb8a2c534661a53c73afb3081cd Linux 3.12 以降、 NFSv4 クライアントがサーバーと通信がなかった場合、 ロックを持っていると「思っている」プロセスがそのファイルに入出力を行うと失敗する。 そのプロセスがそのファイルをいったんクローズし再オープンするまでは入出力は失敗する。 カーネルパラメーター \fInfs.recover_lost_locks\fP を 1 に設定すると、 Linux 3.12 より前の動作にすることができる。 この場合、 サーバーとの通信が再確立された場合、 クライアントがは失われたロックを回復しようとする。 データ破壊が起こる危険性があるため、 このパラメーターはデフォルトでは 0 (無効) になっている。 .SH バグ .SS F_SETFL .\" FIXME . According to POSIX.1-2001, O_SYNC should also be modifiable .\" via fcntl(2), but currently Linux does not permit this .\" See http://bugzilla.kernel.org/show_bug.cgi?id=5994 \fBF_SETFL\fP を使って、 フラグ \fBO_DSYNC\fP と \fBO_SYNC\fP の状態を変更することはできない。これらのフラグの状態を変更しようとした場合には、黙って無視される。 .SS F_GETOWN .\" glibc source: sysdeps/unix/sysv/linux/i386/sysdep.h .\" mtk, Dec 04: some limited testing on alpha and ia64 seems to .\" indicate that ANY negative PGID value will cause F_GETOWN .\" to misinterpret the return as an error. Some other architectures .\" seem to have the same range check as i386. いくつかのアーキテクチャー (特に i386) における Linux システムコールの慣習 のため以下の制限が存在する。 \fBF_GETOWN\fP が返す (負の) プロセスグループID が \-1 から \-4095 の範囲に入った場合、 glibc はこの返り値をシステムコールでエラーが起こったと間違って解釈してしまう。 つまり、 \fBfcntl\fP() の返り値は \-1 となり、 \fIerrno\fP には (正の) プロセスグループID が設定されることになる。Linux 固有の \fBF_GETOWN_EX\fP ではこの問題を回避できる。 glibc バージョン 2.11 以降では、glibc では \fBF_GETOWN_EX\fP を使って \fBF_GETOWN\fP を実装することで、カーネルの \fBF_GETOWN\fP の問題を見えないようにしている。 .SS F_SETOWN .\" Linux 2.4 以前では、非特権プロセスが \fBF_SETOWN\fP を使って、ソケットのファイルディスクリプターの所有者に 呼び出し元以外のプロセス (やプロセスグループ) を指定すると 発生するバグがある。この場合、 呼び出し元が所有者として指定したプロセス (やプロセスグループ) に シグナルを送る許可を持っていたとしても、 \fBfcntl\fP() が \-1 を返し \fIerrno\fP に \fBEPERM\fP を設定することがある。 このエラーが返ったにもかかわらず、ファイルディスクリプターの所有者 は設定され、シグナルはその所有者に送られる。 .SS デッドロックの検出 .\" \fBF_SETLKW\fP 要求を処理する際にカーネルが使用するデッドロック検出アルゴリズムは、 false negative になる場合 (デッドロックを検出できず、 デッドロックになったプロセスは無限に停止する) も false positive になる場合 (デッドロックがない場合でも \fBEDEADLK\fP エラーとなる) もある。 例えば、 カーネルは依存関係の検索を行うロックの深さを 10 ステップに限定しているが、 このためこれよりも長い循環するデッドロックは検出されない。 また、 \fBclone\fP(2) の \fBCLONE_FILES\fP フラグを使って作成された 2 つ以上のプロセスが (カーネルにとって) 衝突するように見えるロックを適用した場合、 カーネルはデッドロックを誤って検出する。 .SS "強制ロック (mandatory locking)" .\" http://marc.info/?l=linux-kernel&m=119013491707153&w=2 .\" .\" Reconfirmed by Jeff Layton .\" From: Jeff Layton redhat.com> .\" Subject: Re: Status of fcntl() mandatory locking .\" Newsgroups: gmane.linux.file-systems .\" Date: 2014-04-28 10:07:57 GMT .\" http://thread.gmane.org/gmane.linux.file-systems/84481/focus=84518 Linux の強制ロックの実装は、 競合条件下で強制ロックが不完全になるような場合がある。 ロックと重なって実行された \fBwrite\fP(2) の呼び出しは強制ロックが獲得された後にもデータを変更することができる。 ロックと重なって実行された \fBread\fP(2) の呼び出しは強制ロックが獲得された後になって行われたデータの変更を 検出することができる。 同様の競合条件が強制ロックと \fBmmap\fP(2) の間にも存在する。それゆえ、強制ロックに頼るのはお薦めできない。 .SH 関連項目 \fBdup2\fP(2), \fBflock\fP(2), \fBopen\fP(2), \fBsocket\fP(2), \fBlockf\fP(3), \fBcapabilities\fP(7), \fBfeature_test_macros\fP(7) Linux カーネルソースの \fIDocumentation/filesystems/\fP ディレクトリ内の \fIlocks.txt\fP, \fImandatory\-locking.txt\fP, \fIdnotify.txt\fP (以前のカーネルでは、これらのファイルは \fIDocumentation/\fP ディレクトリ直下にあり、 \fImandatory\-locking.txt\fP は \fImandatory.txt\fP という名前であった) .SH この文書について この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man\-pages/ に書かれている。