36.10. "fcntl" --- "fcntl" および "ioctl" システムコール
********************************************************

このモジュールでは、ファイル記述子 (file descriptor) に基づいたファイ
ル制御および I/O 制御を実現します。 このモジュールは、 Unix のルーチン
である "fcntl()" および "ioctl()" へのインタフェースです。 これらのシ
ステムコールの完全な説明は、 *fcntl(2)* と *ioctl(2)* のUnix マニュア
ルページを参照してください。

このモジュール内の全ての関数はファイル記述子 *fd* を最初の引数に取りま
す。 この値は "sys.stdin.fileno()" が返すような整数のファイル記述子で
も、 "sys.stdin" 自体のような、純粋にファイル記述子だけを返す
"fileno()" メソッドを提供しているファイルオブジェクトでもかまいません
。

このモジュールでは以下の関数を定義しています:

fcntl.fcntl(fd, op[, arg])

   操作 *op* をファイル記述子 *fd* (または "fileno()" メソッドを提供し
   ているファイルオブジェクト) に対して実行します。 *op* として用いら
   れる値はオペレーティングシステム依存で、 "fcntl" モジュール内に関連
   する C ヘッダファイルと同じ名前が使われている定数の形で利用出来ます
   。引数 *arg* はオプションで、標準では整数値 "0" です。この引数を与
   える場合、整数か文字列の値をとります。引数が無いか整数値の場合、こ
   の関数の戻り値は C 言語の "fcntl()" を呼び出した際の整数の戻り値に
   なります。引数が文字列の場合には、 "struct.pack()" で作られるような
   バイナリの構造体を表します。バイナリデータはバッファにコピーされ、
   そのアドレスが C 言語の "fcntl()" 呼び出しに渡されます。 呼び出しが
   成功した後に戻される値はバッファの内容で、文字列オブジェクトに変換
   されています。 返される文字列は *arg* 引数と同じ長さになます。 この
   値は 1024 バイトに制限されています。 オペレーティングシステムからバ
   ッファに返される情報の長さが 1024 バイトよりも大きい場合、大抵はセ
   グメンテーション違反となるか、より不可思議なデータの破損を引き起こ
   します。

   "fcntl()" が失敗した場合、 "IOError" が送出されます。

fcntl.ioctl(fd, op[, arg[, mutate_flag]])

   この関数は "fcntl()" 関数と同じですが、操作が通常ライブラリモジュー
   ル "termios" で定義されており、引数の扱いがより複雑であるところが異
   なります。

   パラメータ op は32ビットに収まる値に制限されます。 *op* 引数として
   使うのに関係のある追加の定数は "termios" モジュールにあって、関連す
   る C ヘッダファイルで使われているのと同じ名前が付けられています。

   パラメータ *arg* は整数か、存在しない (整数 "0" と等価なものとして
   扱われます) か、(通常の Python 文字列のような) 読み出し専用のバッフ
   ァインタフェースをサポートするオブジェクトか、読み書きバッファイン
   タフェースをサポートするオブジェクトです。

   最後の型のオブジェクトを除き、動作は "fcntl()" 関数と同じです。

   可変なバッファが渡された場合、動作は *mutate_flag* 引数の値で決定さ
   れます。

   この値が偽の場合、バッファの可変性は無視され、動作は読み出しバッフ
   ァの場合と同じになりますが、上で述べた 1024 バイトの制限は回避され
   ます -- 従って、オペレーティングシステムが希望するバッファ長までで
   あれば正しく動作します。

   *mutate_flag* が真の場合、バッファは (実際には) 根底にある
   "ioctl()" システムコールに渡され、後者の戻り値が呼び出し側の Python
   に引き渡され、バッファの新たな内容は  "ioctl()" の動作を反映します
   。 この説明はやや単純化されています。 というのは、与えられたバッフ
   ァが 1024 バイト長よりも短い場合、バッファはまず 1024 バイト長の静
   的なバッファにコピーされてから "ioctl()" に渡され、その後引数で与え
   たバッファに戻しコピーされるからです。

   *mutate_flag* が与えられなかった場合、2.3 ではこの値は偽となります
   。 この仕様は今後のいくつかのバージョンを経た Python で変更される予
   定です: 2.4 では、 *mutate_flag* を提供し忘れると警告が出されますが
   同じ動作を行い、2.5 ではデフォルトの値が真となるはずです。

   "ioctl()" が失敗すると、 "IOError" 例外が送出されます。

   以下に例を示します:

      >>> import array, fcntl, struct, termios, os
      >>> os.getpgrp()
      13341
      >>> struct.unpack('h', fcntl.ioctl(0, termios.TIOCGPGRP, "  "))[0]
      13341
      >>> buf = array.array('h', [0])
      >>> fcntl.ioctl(0, termios.TIOCGPGRP, buf, 1)
      0
      >>> buf
      array('h', [13341])

fcntl.flock(fd, op)

   ファイル記述子 *fd* ("fileno()" メソッドを提供しているファイルオブ
   ジェクトも含む) に対してロック操作 *op* を実行します。 詳細は Unix
   マニュアルの *flock(2)* を参照してください (システムによっては、こ
   の関数は "fcntl()" を使ってエミュレーションされています)。

   "flock()" が失敗すると、 "IOError" 例外が送出されます。

fcntl.lockf(fd, operation[, length[, start[, whence]]])

   本質的に "fcntl()" によるロッキングの呼び出しをラップしたものです。
   *fd* はロックまたはアンロックするファイルのファイル記述子で、
   *operation* は以下の値のうちいずれかになります:

   * "LOCK_UN" -- アンロック

   * "LOCK_SH" -- 共有ロックを取得

   * "LOCK_EX" -- 排他的ロックを取得

   *operation* が "LOCK_SH" または "LOCK_EX" の場合、 "LOCK_NB" とビッ
   ト OR にすることでロック取得時にブロックしないようにすることができ
   ます。 "LOCK_NB" が 使われ、ロックが取得できなかった場合、
   "IOError" が送出され、例外は *errno* 属性を持ち、その値は "EACCESS"
   または "EAGAIN" になります (オペレーティングシステムに依存します;
   可搬性のため、両方の値をチェックしてください)。 少なくともいくつか
   のシステムでは、 ファイル記述子が参照しているファイルが書き込みのた
   めに開かれている場合、 "LOCK_EX" だけしか使うことができません。

   *length* はロックを行いたいバイト数、 *start* はロック領域先頭の
   *whence* からの相対的なバイトオフセット、 *whence* は
   "io.IOBase.seek()" と同じで、具体的には:

   * "0" -- ファイル先頭からの相対位置 ("os.SEEK_SET")

   * "1" -- 現在のバッファ位置からの相対位置 ("os.SEEK_CUR")

   * "2" -- ファイルの末尾からの相対位置 ("os.SEEK_END")

   *start* の標準の値は 0 で、ファイルの先頭から開始することを意味しま
   す。 *whence* の標準の値も 0 です。

以下に (全ての SVR4 互換システムでの) 例を示します:

   import struct, fcntl, os

   f = open(...)
   rv = fcntl.fcntl(f, fcntl.F_SETFL, os.O_NDELAY)

   lockdata = struct.pack('hhllhh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
   rv = fcntl.fcntl(f, fcntl.F_SETLKW, lockdata)

最初の例では、戻り値 *rv* は整数値を保持しています; 二つ目の例では文字
列値を保持しています。 *lockdata* 変数の構造体レイアウトはシステム依存
です --- 従って "flock()" を呼ぶ方がベターです。

参考:

  "os" モジュール
     もし "os" モジュールに "os.O_SHLOCK" と "os.O_EXLOCK" が 存在する
     場合 (BSD のみ)、 "os.open()" 関数は "lockf()" や "flock()" 関数
     を代替できます。
