fcntl --- fcntl および ioctl システムコール¶
このモジュールでは、ファイル記述子 (file descriptor) に基づいたファイル制御および I/O 制御を実現します。
このモジュールは、 Unix のルーチンである fcntl() および ioctl() へのインターフェースです。
これらのシステムコールの完全な説明は、 fcntl(2) と ioctl(2) のUnix マニュアルページを参照してください。
このモジュール内の全ての関数はファイル記述子 fd を最初の引数に取ります。 この値は sys.stdin.fileno() が返すような整数のファイル記述子でも、 sys.stdin 自体のような、純粋にファイル記述子だけを返す fileno() メソッドを提供している io.IOBase オブジェクトでもかまいません。
バージョン 3.8 で変更: The fcntl module now contains F_ADD_SEALS, F_GET_SEALS, and
F_SEAL_* constants for sealing of os.memfd_create() file
descriptors.
バージョン 3.9 で変更: On macOS, the fcntl module exposes the F_GETPATH constant, which obtains
the path of a file from a file descriptor.
On Linux(>=3.15), the fcntl module exposes the F_OFD_GETLK, F_OFD_SETLK
and F_OFD_SETLKW constants, which are used when working with open file
description locks.
このモジュールには、以下の関数が定義されています:
-
fcntl.fcntl(fd, cmd, arg=0)¶ 操作 cmd をファイル記述子 fd (または
fileno()メソッドを提供しているファイルオブジェクト) に対して実行します。 cmd として用いられる値はオペレーティングシステム依存で、fcntlモジュール内に関連する C ヘッダファイルと同じ名前が使われている定数の形で利用出来ます。引数 arg は整数値かbytesオブジェクトをとります。引数が整数値の場合、この関数の戻り値は C 言語のfcntl()を呼び出した際の整数の戻り値になります。引数が bytes の場合には、struct.pack()で作られるようなバイナリの構造体を表します。バイナリデータはバッファにコピーされ、そのアドレスが C 言語のfcntl()呼び出しに渡されます。 呼び出しが成功した後に戻される値はバッファの内容で、bytesオブジェクトに変換されています。 返されるオブジェクトは arg 引数と同じ長さになります。 この値は 1024 バイトに制限されています。 オペレーティングシステムからバッファに返される情報の長さが 1024 バイトよりも大きい場合、大抵はセグメンテーション違反となるか、より不可思議なデータの破損を引き起こします。fcntl()が失敗した場合、OSErrorが送出されます。引数
fd,cmd,argを指定して 監査イベントfcntl.fcntlを送出します。
-
fcntl.ioctl(fd, request, arg=0, mutate_flag=True)¶ この関数は
fcntl()関数と同じですが、引数の扱いがより複雑であるところが異なります。パラメータ request は32ビットに収まる値に制限されます。 request 引数として使うのに関係のある追加の定数は
termiosモジュールにあり、関連する C ヘッダファイルで使われているのと同じ名前が付けられています。パラメタ arg は、整数、 (
bytesのような) 読み出し専用のバッファインターフェースをサポートするオブジェクト、読み書きバッファインターフェースをサポートするオブジェクトのどれかです。最後の型のオブジェクトを除き、動作は
fcntl()関数と同じです。可変なバッファが渡された場合、動作は mutate_flag 引数の値で決定されます。
この値が偽の場合、バッファの可変性は無視され、読み出し専用バッファの場合と同じ動作になりますが、上で述べた 1024 バイトの制限は回避されます -- 従って、オペレーティングシステムが希望するバッファ長までであれば正しく動作します。
mutate_flag が真 (デフォルト) の場合、バッファは (実際には) 根底にある
ioctl()システムコールに渡され、後者の戻り値が呼び出し側の Python に引き渡され、バッファの新たな内容はioctl()の動作を反映します。この説明はやや単純化されています。というのは、与えられたバッファが 1024 バイト長よりも短い場合、バッファはまず 1024 バイト長の静的なバッファにコピーされてからioctl()に渡され、その後引数で与えたバッファに戻しコピーされるからです。ioctl()が失敗すると、OSError例外が送出されます。以下に例を示します:
>>> 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])
引数
fd,request,argを指定して 監査イベントfcntl.ioctlを送出します。
-
fcntl.flock(fd, operation)¶ ファイル記述子 fd (
fileno()メソッドを提供しているファイルオブジェクトも含む) に対してロック操作 operation を実行します。 詳細は Unix マニュアルの flock(2) を参照してください (システムによっては、この関数はfcntl()を使ってエミュレーションされています)。flock()が失敗すると、OSError例外が送出されます。引数
fd,operationを指定して 監査イベントfcntl.flockを送出します。
-
fcntl.lockf(fd, cmd, len=0, start=0, whence=0)¶ 本質的に
fcntl()によるロッキングの呼び出しをラップしたものです。 fd はロックまたはアンロックするファイルのファイル記述子 (fileno()メソッドを提供するファイルオブジェクトも受け付けられます) で、 cmd は以下の値のうちいずれかになります:LOCK_UN-- アンロックLOCK_SH-- 共有ロックを取得LOCK_EX-- 排他的ロックを取得
cmd が
LOCK_SHまたはLOCK_EXの場合、LOCK_NBとビット OR にすることでロック取得時にブロックしないようにすることができます。LOCK_NBが使われ、ロックが取得できなかった場合、OSErrorが送出され、例外は errno 属性を持ち、その値はEACCESまたはEAGAINになります (オペレーティングシステムに依存します; 可搬性のため、両方の値をチェックしてください)。少なくともいくつかのシステムでは、ファイル記述子が参照しているファイルが書き込みのために開かれている場合、LOCK_EXだけしか使うことができません。len はロックを行いたいバイト数、 start はロック領域先頭の whence からの相対的なバイトオフセット、 whence は
io.IOBase.seek()と同じで、具体的には:0-- ファイル先頭からの相対位置 (os.SEEK_SET)1-- 現在のバッファ位置からの相対位置 (os.SEEK_CUR)2-- ファイルの末尾からの相対位置 (os.SEEK_END)
start の標準の値は 0 で、ファイルの先頭から開始することを意味します。len の標準の値は 0 で、ファイルの終了までロックすることを表します。whence の標準の値も 0 です。
引数
fd,cmd,len,start,whenceを指定して 監査イベントfcntl.lockfを送出します。
以下に (全ての 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 は整数値を保持しています; 二つ目の例では bytes オブジェクトを保持しています。 lockdata 変数の構造体レイアウトはシステム依存です --- 従って flock() を呼ぶ方が良いでしょう。
参考
osモジュールもし
osモジュールにos.O_SHLOCKとos.O_EXLOCKが 存在する場合 (BSD のみ)、os.open()関数はlockf()やflock()関数を代替できます。