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
模組現在包含 F_ADD_SEALS
、F_GET_SEALS
和 F_SEAL_*
常量,用於密封 os.memfd_create()
檔案描述符。
在 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)上進行重新連結來與其他檔案共享一個檔案的一些資料。 此行為通常被稱為“寫入時複製”。
在 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_SEAL_FUTURE_WRITE
常量,以用於 F_ADD_SEALS
和 F_GET_SEALS
操作。 在 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
常量。
該模組定義了以下函式
- fcntl.fcntl(fd, cmd, arg=0)¶
對檔案描述符 fd 執行操作 cmd(也接受提供
fileno()
方法的檔案物件)。 用於 cmd 的值取決於作業系統,並且在fcntl
模組中可用作常量,使用與相關 C 標頭檔案中相同的名稱。 引數 arg 可以是整數值,也可以是bytes
物件。 如果是整數值,則此函式的返回值是 Cfcntl()
呼叫的整數返回值。 當引數是位元組時,它表示一個二進位制結構,例如由struct.pack()
建立。 二進位制資料被複制到緩衝區,該緩衝區的地址被傳遞給 Cfcntl()
呼叫。 成功呼叫後的返回值是緩衝區的內容,轉換為bytes
物件。 返回物件的長度將與 arg 引數的長度相同。 這限制為 1024 位元組。 如果作業系統在緩衝區中返回的資訊大於 1024 位元組,則很可能導致分段違規或更細微的資料損壞。如果
fcntl()
呼叫失敗,則會引發OSError
。引發一個 審計事件
fcntl.fcntl
,引數為fd
、cmd
和arg
。
- fcntl.ioctl(fd, request, arg=0, mutate_flag=True)¶
此函式與
fcntl()
函式相同,只是引數處理更加複雜。request 引數的值被限制在 32 位以內。作為 request 引數使用的其他相關常量可以在
termios
模組中找到,名稱與相關 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.ioctl
,引數為fd
、request
和arg
。
- fcntl.flock(fd, operation)¶
在檔案描述符 fd 上執行鎖定操作 operation (也接受提供
fileno()
方法的檔案物件)。有關詳細資訊,請參閱 Unix 手冊 flock(2)。(在某些系統中,此函式是使用fcntl()
模擬的。)如果
flock()
呼叫失敗,則會引發OSError
異常。引發一個 審計事件
fcntl.flock
,引數為fd
和operation
。
- 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
,並且該異常將具有一個設定為EACCES
或EAGAIN
的 errno 屬性(取決於作業系統;為了保證可移植性,請檢查這兩個值)。至少在某些系統上,只有當檔案描述符引用為寫入開啟的檔案時,才能使用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。
引發一個 審計事件
fcntl.lockf
,引數為fd
、cmd
、len
、start
和whence
。
示例(所有示例均在 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()
呼叫可能更好。