fcntl

Autres langues

Langue: ja

Version: 2005-05-20 (fedora - 25/11/07)

Section: 2 (Appels système)

名前

fcntl - ファイルディスクリプタの操作を行う

書式

 #include <unistd.h>
 #include <fcntl.h>
 
 int fcntl(int fd, int cmd);
 int fcntl(int fd, int cmd, long arg);
 int fcntl(int fd, int cmd, struct flock *lock);
 

説明

fcntl() は、オープンされたファイルディスクリプタ fd に関して下記の操作を行う。操作は cmd によって決まる:

ファイルディスクリプタの複製

F_DUPFD
利用可能なファイルディスクリプタのうち、 arg 以上で最小のものを探し、 fd のコピーとする。これは別の形の dup2(2) である。 dup2(2) では指定されたディスクリプタが使われる点が違う。

成功すると、新しいディスクリプタが返される。

詳細は dup(2) を参照のこと。

ファイルディスクリプタ・フラグ

以下のコマンドを使って、ファイルディスクリプタに関連するフラグ を操作することができる。 現在のところ、定義されているフラグは一つだけである: FD_CLOEXEC, close-on-exec フラグ。 FD_CLOEXEC ビットが 0 なら、ファイルディスクリプタは execve(2) を行ってもオープンされたままだが、そうでない場合はクローズされる。
F_GETFD
ファイルディスクリプタ・フラグを読み出す。
F_SETFD
ファイルディスクリプタ・フラグに arg で指定した値を設定する。

ファイル状態フラグ

オープンファイル記述 (open file description) には、 ファイル記述毎に設定される状態フラグがいくつかある。これらのフラグは open(2) によって初期化され、 fcntl(2) により変更することもできる。これらは、 (dup(2), fcntl(F_DUPFD), fork(2) などで) 複製されたファイルディスクリプタ同士は 同じオープンファイル記述を参照する。 そのため、 同じファイル状態フラグが共有される。

ファイル状態フラグとその意味は open(2) で説明されている。

F_GETFL
ファイル状態フラグを読み出す。
F_SETFL
ファイル状態フラグに 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 フィールドで、ロックを行いたいバイト範囲を指定する。 l_start はロックを行う領域の開始オフセットである。 その意味は l_whence により異なる: l_whenceSEEK_SET の場合はファイルの先頭からのオフセット、 l_whenceSEEK_CUR の場合は現在のファイルオフセットからのオフセット、 l_whenceSEEK_END の場合はファイルの末尾からのオフセットと解釈される。 後ろの2つの場合には、 ファイルの先頭より前にならない範囲で、 l_start に負の値を指定することができる。

l_len はロックを行う領域のバイト数を示し、非負の整数で指定する (下記の 注意の章も参照)。 バイト数の指定は、ファイルの末尾を超えた範囲まで行ってもよいが、 ファイルの先頭より前になってはいけない。 l_len が 0 の場合は特別な意味を持つ: l_whence and l_start で指定される位置からファイルの末尾までの全てのバイトをロックする (ファイルがどんなに大きくなったとしてもファイルの末尾までロックする)。

l_type フィールドは、ファイルに対して読み出しロック (F_RDLCK) と書き込みロック (F_WRLCK) のどちらを 設定するかを指定する。 ファイルのある領域に対して、読み出しロック (共有ロック) を保持できる プロセス数に制限はないが、書き込みロック (排他ロック) を保持できる のは一つのプロセスだけである。排他ロックを設定すると、(共有ロックか 排他ロックにかかわらず) 他のロックは何も設定できない。 一つのプロセスは、ファイルのある領域に対して一種類のロックしか保持できない。 新規のロックがロックが設定されている領域に対して適用されると、既存のロック は新規のロックの種別に変換される (新規のロックで指定されたバイト範囲が既存ロックの範囲と一致する場合以外では、 変換の過程で既存のロックの分割、縮小、結合が行われることがある)。

F_SETLK
(l_typeF_RDLCKF_WRLCK の場合は) ロックの獲得を、 (F_UNLCK の場合は) ロックの解放を、 flock 構造体のフィールド l_whence, l_start, l_len で指定された範囲のバイトに対して行う。 指定されたロックが他のプロセスが設定しているロックと衝突する場合は、 -1 を返し、 errnoEACCESEAGAIN を設定する。
F_SETLKW
F_SETLK と同様だが、こちらではそのファイルに対して衝突するロックが 適用されていた場合に、そのロックが解放されるのを待つ点が異なる。 待っている間にシグナルを受けた場合は、システムコールは中断され、 (シグナルハンドラが戻った直後に) 返り値 -1 を返す (また errnoEINTR が設定される)。
F_GETLK
このコールの呼び出し時には、 lock にはそのファイルに適用しようとするロックに関する情報が入っている。 ロックを適用できる場合には、 fcntl() は実際にはロックを行わず、構造体 lockl_type フィールドに F_UNLCK を設定し、他のフィールドは変更せずに、復帰する。 違う種別のロックが (一つもしくは複数) 適用されていて ロックを適用できないような場合には、 fcntl() は、原因となったロックの一つについての詳細情報を構造体 lock のフィールド l_type, l_whence, l_start, l_len に格納し、また l_pid にロックを保持しているプロセスの PID を設定して、復帰する。

読み出しロックを適用するには、 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 フラグが有効になっているときは、システムコールはエラー EAGAINEWOULDBLOCK で失敗する。

強制ロックを使用するためには、ロック対象のファイルが含まれるファイルシステム と、ロック対象のファイル自身の両方について、強制ロックが有効になっていなけれ ばならない。ファイルシステムについて強制ロックを有効にするには、 mount(8) に "-o mand" オプションを渡すか、 mount(2) に MS_MANDLOCK フラグを指定する。ファイルについて強制ロックを有効にするには、 そのファイルのグループ実行許可 (group execute permission) を無効とし、 かつ set-group-ID 許可ビットを有効にする (chmod(1) と chmod(2) を参照)。

シグナルの管理

F_GETOWN, F_SETOWN, F_GETSIG, F_SETSIG は、I/O が利用可能になったことを示すシグナルを管理するために使用する。
F_GETOWN
ファイルディスクリプタ fd のイベントに対するシグナル SIGIO および SIGURG を受けているプロセスのプロセスID かプロセスグループを取得する。 プロセスID は正の値として返される。 プロセスグループID は負の値として返される (下記のバグの章を参照)。
F_SETOWN
ファイルディスクリプタ fd のイベント発生を知らせるシグナル SIGIOSIGURG を受けるプロセスの プロセス ID またはプロセスグループID を設定する。 プロセスID は正の値として指定し、 プロセスグループID は負の値として指定する。 ほとんどの場合、呼び出し元プロセスは所有者として自分自身を指定する (つまり arggetpid(2) を指定する)。

fcntl() の F_SETFL コマンドを使用してファイルディスクリプタに O_ASYNC 状態フラグを設定した場合には、そのファイルディスクリプタへの 入出力が可能になる度に SIGIO シグナルが送られる。 F_SETSIGSIGIO 以外の別のシグナルの配送を受けられるように するのにも使うことができる。 許可 (permission) のチェックで失敗した場合には、 シグナルは黙って捨てられる。

F_SETOWN により指定された所有者のプロセス (またはプロセスグループ) に シグナルを送る際には、 kill(2) に書かれているのと同じ許可のチェックが行われる。 このとき、シグナルを送信するプロセスは F_SETOWN を使ったプロセスである (但し、下記の「バグ」の章を参照のこと)。

ファイルディスクリプタがソケットを参照している場合は、 F_SETOWN を使用して、ソケットに帯域外 (out-of-band) データが届いた時に SIGURG シグナルを配送する相手を選択することもできる (SIGURG が送られた場合には select(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 では一つのプロセスに対してキューに入れられるリアルタイム シグナルの数に上限が設けられており (getrlimit(2) と signal(7) を参照)、この上限に達するとカーネルは SIGIO シグナルを配送する。この SIGIO シグナルは、指定されたスレッドではなくプロセス全体に送られる。

F_GETSIG
入力や出力が可能になった場合に送るシグナルを取得する。 値ゼロは SIGIO を送ることを意味する。 (SIGIO を含む) 他の値はいずれも、 SIGIO の代わりに送るシグナル番号を表す。 後者の場合、シグナルハンドラを SA_SIGINFO フラグ付きで設定すれば、ハンドラで追加の情報を得ることができる。
F_SETSIG
入力や出力が可能になった場合に送るシグナルを設定する。 値ゼロは SIGIO を送ることを意味する。 (SIGIO を含む) 他の値はいずれも、 SIGIO の代わりに送るシグナル番号を表す。 後者の場合、シグナルハンドラを SA_SIGINFO フラグ付きで設定すれば、 ハンドラで追加の情報を得ることができる。

また、 F_SETSIG に 0 以外の値を渡すと、シグナルの受信者をプロセス全体から プロセス内の特定のスレッドに変更される。詳細は F_SETOWN の説明を参照のこと。

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 が設定されている場合、シグナルハンドラのための追加の情報が得られる。

これらの機構を使用することで、ほとんどの場合で select(2) や poll(2) を使用せずに完全な非同期 I/O を実装することができる。

O_ASYNC, F_GETOWN, F_SETOWN の使用は BSD と Linux に特有である。 F_GETSIGF_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
arg の内容に基いてファイルのリースの設定、削除を行う。整数 arg には以下の値が指定できる:
F_RDLCK 読み出しリースを取得する。これにより、 そのファイルが書き込み用にオープンされたり、ファイルが切り詰められた場合に、 呼び出し元のプロセスに通知が行われるようになる。 読み出しリースを設定できるのは、読み出し専用でオープンされている ファイルディスクリプタに対してのみである。
F_WRLCK
書き込みリースを取得する。これにより、 (読み出し用か書き込み用にかかわらず) そのファイルがオープンされたり、 ファイルが切り詰められた場合に、呼び出し元のプロセスに通知が行われるようになる。 書き込みリースは、そのファイルをオープンしているプロセスが他にない場合にのみ 設定できる。
F_UNLCK
そのファイルからリースを削除する。

一つのプロセスは、一つのファイルに対して一種類のリースしか 保持できない。

リースの取得は通常のファイル (regular file) に対してのみ可能である。 非特権プロセスがリースを取得できるのは、UID がプロセスの ファイルシステムUID と一致するファイルに対してだけである。 CAP_LEASE ケーパビリティを持つプロセスは任意のファイルに対してリースを取得できる。

F_GETLEASE
fd が参照するファイルに対して保持しているリースの種別を取得する。 F_RDLCK, F_WRLCK, F_UNLCK のいずれかが返される。 F_RDLCK, F_WRLCK はそれぞれ、呼び出し元プロセスが読み出しリース、書き込みリースを 保持していることを示し、 F_UNLCK はリースを何も保持していないことを示す。 (fcntl() の第3引き数は省略される。)

あるプロセス ("lease folder") が F_SETLEASE で設定されたリースと矛盾するような open(2) や truncate(2) を実行した場合、 そのシステムコールはカーネルによって停止され、 カーネルは lease holder にシグナル (デフォルトでは SIGIO) を送って通知を行う。 lease holder はこのシグナルを受信したときにはきちんと対応すべきである。 具体的には、別のプロセスがそのファイルにアクセスするための準備として 必要な後片付け (例えば、キャッシュされたバッファのフラッシュ) を すべて行ってから、そのファイルのリースの削除または格下げを行う。 リースを削除をするには、 argF_UNLCK を指定して F_SETLEASE を実行する。 ファイルに書き込みリースを保持をしていて、 lease breaker が読み出し用にそのファイルをオープンしようとしている場合、 適用するリースを読み出しリースに格下げすれば十分である。 これをするには、 argF_RDLCK を指定して F_SETLEASE を実行する。

lease holder が /proc/sys/fs/lease-break-time で指定された秒数以内にリースの格下げか削除を行えなかった場合、 カーネルは強制的にその lease holder のリースを削除もしくは格下げを行う。

一度リースの削除か格下げが自発的もしくは強制的に行われると、 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
(Linux 2.4 以降) fd で参照されるディレクトリか、その中にあるファイルに変更があった場合に 通知を行う。どのイベントを通知するかは arg で指定する。 arg はビットマスクで、以下のビットの 0個以上の論理和をとったものを指定する。
ビット 説明 (ディレクトリのイベント)
DN_ACCESS
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)」であり、 アプリケーション側でその後さらに通知を受信したい場合は 再登録しなければならない。 argDN_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_DUPFD
新しいディスクリプタを返す。
F_GETFD
フラグの値を返す。
F_GETFL
フラグの値を返す。
F_GETOWN
ディスクリプタの所有者を返す。
F_GETSIG
読み込みや書き出しが可能になった時に送られるシグナルの値、もしくは 伝統的な SIGIO 動作の場合にはゼロを返す。
他の全てのコマンドは 0 を返す。

エラーの時は -1 が返され、 errno に適切な値が設定される。

エラー

EACCESEAGAIN
他のプロセスが保持しているロックによって操作が禁止されている。
EAGAIN
そのファイルは他のプロセスによってメモリ・マップされているため、 操作が禁止されている。
EBADF
fd がオープンされたファイルディスクリプタでない。 あるいはコマンドが F_SETLK または F_SETLKW だったが、対象のファイルディスクリプタのオープンモードが 必要となるロックの型にマッチしていない。
EDEADLK
指定された F_SETLKW コマンドを実行した場合にはデッドロックになることが検出された。
EFAULT
lock が利用可能なアドレス空間の外部にある。
EINTR
F_SETLKW コマンドがシグナルにより割り込まれた。 F_GETLKF_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 だけである。

F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE, F_SETLEASE は Linux 固有である (これらの定義を有効にするには _GNU_SOURCE マクロを定義すること)。

注意

エラーの際の返り値が dup2(2) と F_DUPFD では異なっている。

カーネル 2.0 以降では、 flock(2) と fcntl(2) が設定するロック種別の間に相互作用はない。

POSIX.1-2001 では l_len を負の値にすることができる (この場合、ロックされるバイト位置は l_start+l_len 以上 l_start-1 以下となる)。 この動作は Linux 2.4.21 および 2.5.49 以降でサポートされている。

システムによっては、 struct flock に上記以外のフィールドがあるものもある (例えば l_sysid)。 はっきりと言えることは、ロックを保持しているプロセスが別のマシンに存在 する場合には、 l_pid だけはあまり役にたたないだろうということである。

バグ

いくつかのアーキテクチャ (特に x86) における Linux システムコールの慣習 のため以下の制限が存在する。 F_GETOWN が返す (負の) プロセスグループID が -1 から -4095 の範囲に入った場合、 glibc はこの返り値をシステムコールでエラーが起こったと 間違って解釈してしまう。つまり、 fcntl() の返り値は -1 となり、 errno には (正の) プロセスグループID が設定されることになる。

Linux 2.4 以前では、非特権プロセスが F_SETOWN を使って、ソケットのファイルディスクリプタの所有者に 呼び出し元以外のプロセス (やプロセスグループ) を指定すると 発生するバグがある。この場合、 呼び出し元が所有者として指定したプロセス (やプロセスグループ) に シグナルを送る許可を持っていたとしても、 fcntl() が -1 を返し errnoEPERM を設定することがある。 このエラーが返ったにもかかわらず、ファイルディスクリプタの所有者 は設定され、シグナルはその所有者に送られる。

関連項目

dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7)

カーネルソース内の Documentation/locks.txt, Documentation/mandatory.txt, Documentation/dnotify.txt も参照のこと。