fcntl —— 系統調用 fcntl 和 ioctl?
本模塊基于文件描述符來進行文件控制和 I/O 控制。它是 Unix 系統調用 fcntl() 和 ioctl() 的接口。關于這些調用的完整描述,請參閱 Unix 手冊的 fcntl(2) 和 ioctl(2) 頁面。
本模塊的所有函數都接受文件描述符 fd 作為第一個參數。可以是一個整數形式的文件描述符,比如 sys.stdin.fileno() 的返回結果,或為 io.IOBase 對象,比如 sys.stdin 提供一個 fileno(),可返回一個真正的文件描述符。
這個模塊定義了以下函數:
-
fcntl.fcntl(fd, cmd, arg=0)? 對文件描述符 fd 執行 cmd 操作(能夠提供
fileno()方法的文件對象也可以接受)。 cmd 可用的值與操作系統有關,在fcntl模塊中可作為常量使用,名稱與相關 C 語言頭文件中的一樣。參數 arg 可以是整數或bytes對象。若為整數值,則本函數的返回值是 C 語言fcntl()調用的整數返回值。若為字節串,則其代表一個二進制結構,比如由struct.pack()創建的數據。該二進制數據將被復制到一個緩沖區,緩沖區地址傳給 C 調用fcntl()。調用成功后的返回值位于緩沖區內,轉換為一個bytes對象。返回的對象長度將與 arg 參數的長度相同。上限為 1024 字節。如果操作系統在緩沖區中返回的信息大于 1024 字節,很可能導致內存段沖突,或更為不易察覺的數據錯誤。如果
fcntl()調用失敗,會觸發OSError。
-
fcntl.ioctl(fd, request, arg=0, mutate_flag=True)? 本函數與
fcntl()函數相同,只是參數的處理更加復雜。request 參數的上限是 32位。
termios模塊中包含了可用作 request 參數其他常量,名稱與相關 C 頭文件中定義的相同。參數 arg 可為整數、支持只讀緩沖區接口的對象(如
bytes)或支持讀寫緩沖區接口的對象(如bytearray)。除了最后一種情況,其他情況下的行為都與
fcntl()函數一樣。如果傳入的是個可變緩沖區,那么行為就由 mutate_flag 參數決定。
如果為 False,緩沖區的可變性將被忽略,行為與只讀緩沖區一樣,只是沒有了上述 1024 字節的上限——只要傳入的緩沖區能容納操作系統放入的數據即可。
如果 mutate_flag 為 True(默認值),那么緩沖區(實際上)會傳給底層的 系統調用
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])
-
fcntl.flock(fd, operation)? 在文件描述符 fd 上執行加鎖操作 operation (也接受能提供
fileno()方法的文件對象)。 詳見 Unix 手冊 flock(2)。 (在某些系統中,此函數是用fcntl()模擬出來的。)如果
flock()調用失敗,就會觸發OSError異常。
-
fcntl.lockf(fd, cmd, len=0, start=0, whence=0)? This is essentially a wrapper around the
fcntl()locking calls. fd is the file descriptor of the file to lock or unlock, and cmd is one of the following values:LOCK_UN——解鎖LOCK_SH—— 獲取一個共享鎖LOCK_EX—— 獲取一個獨占鎖
如果 cmd 為
LOCK_SH或LOCK_EX,則還可以與LOCK_NB進行按位或運算,以避免在獲取鎖時出現阻塞。 如果用了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。
示例(都是運行于符合 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() 調用會更好。
