other versions
other sections
FCNTL(2) | Linux Programmer's Manual | FCNTL(2) |
名前¶
fcntl - ファイルディスクリプタの操作を行う書式¶
#include <unistd.h> #include <fcntl.h>int fcntl(int fd, int cmd, ... /* arg */ );
説明¶
fcntl() は、オープンされたファイルディスクリプタ fd に関して下記の操作を行う。操作は cmd によって決まる:ファイルディスクリプタの複製¶
- 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 で指定した値を設定する。
ファイル状態フラグ¶
オープンファイル記述 (open file description) には、 ファイル記述毎に設定される状態フラグがいくつかある。これらのフラグは open(2) によって初期化され、 fcntl(2) により変更することもできる。これらは、 ( dup(2), fcntl(F_DUPFD), fork(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 フラグだけである。
アドバイザリ・ロック¶
F_GETLK, F_SETLK, F_SETLKW は、レコード・ロックの獲得/解放/テストのために使用する (レコード・ロックはファイルセグメント・ロックや ファイル領域ロックとも呼ばれる)。 三番目の引き数 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 フィールドで、ロックを行いたいバイト範囲を指定する。 ファイルの末尾より後ろのバイトをロックすることはできるが、 ファイルの先頭より前のバイトをロックすることはできない。
- 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 を設定して、復帰する。
強制ロック (mandatory locking)¶
上述のロックにはアドバイザリ・ロック (advisory lock) と強制ロック (mandatory lock) の二種類があるが、デフォルトではアドバイザリ・ロックとなる。シグナルの管理¶
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)
を指定する)。
- スレッドグループをサポートしているスレッドライブラリ (例えば 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
が指す構造体に格納されて返される。構造体は以下の通りである。
type フィールドは、 F_OWNER_TID , F_OWNER_PID , F_OWNER_PGRP のいずれか一つの値となる。 pid フィールドは、スレッド ID、プロセス ID、プロセスグループ ID を 表す正の整数である。詳細は F_SETOWN_EX を参照。
struct f_owner_ex { int type; pid_t pid; };
- F_SETOWN_EX (struct f_owner_ex *) (Linux 2.6.32 以降)
- この操作は F_SETOWN と同様の処理を行う。 この操作を使うと、I/O が利用可能になったことを示すシグナルを、 特定のスレッド、プロセス、プロセスグループに送ることができる ようになる。 呼び出し元は、 arg 経由でシグナルの配送先を指定する。 arg は f_owner_ex 構造体へのポインタである。 type フィールドは以下のいずれかの値を取り、 この値により pid がどのように解釈されるかが規定される。
- 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
フラグ付きで設定すれば、
ハンドラで追加の情報を得ることができる。
リース (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
- そのファイルからリースを削除する。
- F_GETLEASE (void)
- ファイルディスクリプタ fd に対して設定されているリースの種別を取得する。 F_RDLCK, F_WRLCK, F_UNLCK のいずれかが返される。 F_RDLCK, F_WRLCK はそれぞれ、読み出しリース、書き込みリースが設定されていることを示し、 F_UNLCK はリースが何も設定されていないことを示す。 arg は無視される。
ファイルやディレクトリの変更の通知 (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
機能検査マクロを定義しなければならない。)
パイプの容量の変更¶
- 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 を返す。
エラー¶
- 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 だけである。注意¶
元々の Linux の fcntl() システムコールは ( flock 構造体で) 大きな ファイルオフセットを扱えるように設計されていなかった。 その結果、Linux 2.4 で fcntl64() システムコールが追加された。 この新しいシステムコールは、ファイルのロックに flock64 という別の 構造体を利用し、これに対応するコマンドとして F_GETLK64, F_SETLK64, F_SETLKW64 を使用する。 しかし、 glibc を使うアプリケーションではこれらの詳細を無視することが できる。 glibc の fcntl のラッパー関数は新しいシステムコールが 利用できる場合はそれを利用するようになっているからである。バグ¶
いくつかのアーキテクチャ (特に 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 の問題を見えないようにしている。関連項目¶
dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7) カーネルソースの Documentation/filesystems/ ディレクトリ内の locks.txt, mandatory-locking.txt, dnotify.txt も参照のこと。 (以前のカーネルでは、これらのファイルは Documentation/ ディレクトリ直下にあり、 mandatory-locking.txt は mandatory.txt という名前であった。)この文書について¶
この man ページは Linux man-pages プロジェクトのリリース 3.41 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2012-04-15 | Linux |