fcntl
--- fcntl
和 ioctl
系統呼叫¶
此模組對檔案描述符執行檔案和 I/O 控制。它是 fcntl()
和 ioctl()
Unix 例程的介面。有關完整的詳細資訊,請參閱 fcntl(2) 和 ioctl(2) Unix 手冊頁。
可用性: Unix,不包括 WASI。
此模組中的所有函式都接受一個檔案描述符 fd 作為其第一個引數。這可以是一個整數檔案描述符,例如 sys.stdin.fileno()
返回的值,也可以是一個 io.IOBase
物件,例如 sys.stdin
本身,它提供了一個返回真實檔案描述符的 fileno()
方法。
在 3.8 版更改: fcntl
模組現在包含用於密封 os.memfd_create()
檔案描述符的 F_ADD_SEALS
、F_GET_SEALS
和 F_SEAL_*
常量。
在 3.9 版更改: 在 macOS 上,fcntl
模組公開了 F_GETPATH
常量,用於從檔案描述符獲取檔案路徑。在 Linux(>=3.15) 上,fcntl
模組公開了 F_OFD_GETLK
、F_OFD_SETLK
和 F_OFD_SETLKW
常量,這些常量用於處理開啟檔案描述符鎖。
在 3.10 版更改: 在 Linux >= 2.6.11 上,fcntl
模組公開了 F_GETPIPE_SZ
和 F_SETPIPE_SZ
常量,它們分別允許檢查和修改管道的大小。
在 3.11 版更改: 在 FreeBSD 上,fcntl
模組公開了 F_DUP2FD
和 F_DUP2FD_CLOEXEC
常量,它們允許複製一個檔案描述符,後者還會額外設定 FD_CLOEXEC
標誌。
在 3.12 版更改: 在 Linux >= 4.5 上,fcntl
模組公開了 FICLONE
和 FICLONERANGE
常量,它們允許在某些檔案系統(例如 btrfs、OCFS2 和 XFS)上透過 reflinking 將一個檔案的資料與另一個檔案共享。此行為通常稱為“寫入時複製”(copy-on-write)。
在 3.13 版更改: 在 Linux >= 2.6.32 上,fcntl
模組公開了 F_GETOWN_EX
、F_SETOWN_EX
、F_OWNER_TID
、F_OWNER_PID
、F_OWNER_PGRP
常量,它們允許將 I/O 可用性訊號定向到特定的執行緒、程序或程序組。在 Linux >= 4.13 上,fcntl
模組公開了 F_GET_RW_HINT
、F_SET_RW_HINT
、F_GET_FILE_RW_HINT
、F_SET_FILE_RW_HINT
和 RWH_WRITE_LIFE_*
常量,它們允許通知核心關於在給定 inode 或透過特定開啟檔案描述符上的寫入的相對預期壽命。在 Linux >= 5.1 和 NetBSD 上,fcntl
模組公開了用於 F_ADD_SEALS
和 F_GET_SEALS
操作的 F_SEAL_FUTURE_WRITE
常量。在 FreeBSD 上,fcntl
模組公開了 F_READAHEAD
、F_ISUNIONSTACK
和 F_KINFO
常量。在 macOS 和 FreeBSD 上,fcntl
模組公開了 F_RDAHEAD
常量。在 NetBSD 和 AIX 上,fcntl
模組公開了 F_CLOSEM
常量。在 NetBSD 上,fcntl
模組公開了 F_MAXFD
常量。在 macOS 和 NetBSD 上,fcntl
模組公開了 F_GETNOSIGPIPE
和 F_SETNOSIGPIPE
常量。
在 3.14 版更改: 在 Linux >= 6.1 上,fcntl
模組公開了 F_DUPFD_QUERY
,用於查詢指向同一檔案的檔案描述符。
該模組定義了以下函式:
- fcntl.fcntl(fd, cmd, arg=0, /)¶
對檔案描述符 fd 執行操作 cmd(也接受提供
fileno()
方法的檔案物件)。用於 cmd 的值是作業系統相關的,並在fcntl
模組中作為常量提供,使用的名稱與相關 C 標頭檔案中的名稱相同。引數 arg 可以是整數值、類位元組物件或字串。arg 的型別和大小必須與相關 C 文件中指定的操作引數的型別和大小相匹配。當 arg 是一個整數時,該函式返回 C
fcntl()
呼叫的整數返回值。當引數是類位元組物件時,它表示一個二進位制結構,例如由
struct.pack()
建立的結構。字串值會使用 UTF-8 編碼為二進位制。二進位制資料被複制到一個緩衝區,其地址被傳遞給 Cfcntl()
呼叫。成功呼叫後的返回值是緩衝區的內容,轉換為bytes
物件。返回物件的長度將與 arg 引數的長度相同。這被限制在 1024 位元組以內。如果
fcntl()
呼叫失敗,則會引發OSError
。備註
如果 arg 的型別或大小與操作引數的型別或大小不匹配(例如,當期望一個指標時傳遞了一個整數,或者作業系統在緩衝區中返回的資訊大於 1024 位元組),這很可能會導致段錯誤或更細微的資料損壞。
觸發一個引數為
fd
,cmd
,arg
的 審計事件fcntl.fcntl
。
- fcntl.ioctl(fd, request, arg=0, mutate_flag=True, /)¶
此函式與
fcntl()
函式相同,只是引數處理更為複雜。request 引數受限於能放入 32 位或 64 位的值,具體取決於平臺。其他可用作 request 引數的常量可以在
termios
模組中找到,其名稱與相關 C 標頭檔案中使用的名稱相同。引數 arg 可以是一個整數、一個類位元組物件或一個字串。arg 的型別和大小必須與相關 C 文件中指定的操作引數的型別和大小相匹配。
如果 arg 不支援讀寫緩衝區介面,或者 mutate_flag 為 false,則其行為與
fcntl()
函式相同。如果 arg 支援讀寫緩衝區介面(如
bytearray
)並且 mutate_flag 為 true(預設值),那麼緩衝區(實際上)被傳遞給底層的ioctl()
系統呼叫,後者的返回碼被傳回給呼叫它的 Python,並且緩衝區的新內容反映了ioctl()
的操作。這是一個輕微的簡化,因為如果提供的緩衝區小於 1024 位元組長,它會首先被複制到一個 1024 位元組長的靜態緩衝區,然後該靜態緩衝區被傳遞給ioctl()
,並再被複制回提供的緩衝區。如果
ioctl()
呼叫失敗,將引發OSError
異常。備註
如果 arg 的型別或大小與操作引數的型別或大小不匹配(例如,當期望一個指標時傳遞了一個整數,或者作業系統在緩衝區中返回的資訊大於 1024 位元組,或者可變類位元組物件的大小太小),這很可能會導致段錯誤或更細微的資料損壞。
一個例子:
>>> 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
。在 3.14 版更改: 在系統呼叫期間,GIL 總是被釋放。因 EINTR 而失敗的系統呼叫會自動重試。
- fcntl.flock(fd, operation, /)¶
對檔案描述符 fd 執行鎖操作 operation(也接受提供
fileno()
方法的檔案物件)。詳情請參閱 Unix 手冊 flock(2)。(在某些系統上,此函式是使用fcntl()
模擬的。)如果
flock()
呼叫失敗,將引發OSError
異常。觸發一個引數為
fd
,operation
的 審計事件fcntl.flock
。
- fcntl.lockf(fd, cmd, len=0, start=0, whence=0, /)¶
這本質上是
fcntl()
鎖定呼叫的一個包裝器。fd 是要鎖定或解鎖的檔案的檔案描述符(也接受提供fileno()
方法的檔案物件),而 cmd 是以下值之一:- fcntl.LOCK_UN¶
釋放一個現有的鎖。
- fcntl.LOCK_SH¶
獲取一個共享鎖。
- fcntl.LOCK_EX¶
獲取一個排他鎖。
- fcntl.LOCK_NB¶
與任何其他三個
LOCK_*
常量進行按位或運算,以使請求非阻塞。
如果使用
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()
呼叫可能更好。