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()
调用可能更好。