fcntl
--- fcntl
和 ioctl
系统调用¶
本模块基于文件描述符来执行文件和 I/O 控制。 它是 fcntl()
和 ioctl()
Unix 例程的接口。 请参阅 fcntl(2) 和 ioctl(2) Unix 手册页了解详情。
Availability: Unix, not 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, /)¶
Perform the operation cmd on file descriptor fd (file objects providing a
fileno()
method are accepted as well). The values used for cmd are operating system dependent, and are available as constants in thefcntl
module, using the same names as used in the relevant C header files. The argument arg can either be an integer value, abytes
object, or a string. The type and size of arg must match the type and size of the argument of the operation as specified in the relevant C documentation.When arg is an integer, the function returns the integer return value of the C
fcntl()
call.When the argument is bytes, it represents a binary structure, for example, created by
struct.pack()
. A string value is encoded to binary using the UTF-8 encoding. The binary data is copied to a buffer whose address is passed to the Cfcntl()
call. The return value after a successful call is the contents of the buffer, converted to abytes
object. The length of the returned object will be the same as the length of the arg argument. This is limited to 1024 bytes.如果
fcntl()
调用失败,将引发OSError
。备注
If the type or the size of arg does not match the type or size of the argument of the operation (for example, if an integer is passed when a pointer is expected, or the information returned in the buffer by the operating system is larger than 1024 bytes), this is most likely to result in a segmentation violation or a more subtle data corruption.
引发一个 审计事件
fcntl.fcntl
并附带参数fd
,cmd
,arg
。
- fcntl.ioctl(fd, request, arg=0, mutate_flag=True, /)¶
本函数与
fcntl()
函数相同,只是参数的处理更加复杂。The request parameter is limited to values that can fit in 32-bits or 64-bits, depending on the platform. Additional constants of interest for use as the request argument can be found in the
termios
module, under the same names as used in the relevant C header files.The parameter arg can be an integer, a bytes-like object, or a string. The type and size of arg must match the type and size of the argument of the operation as specified in the relevant C documentation.
If arg does not support the read-write buffer interface or the mutate_flag is false, behavior is as for the
fcntl()
function.If arg supports the read-write buffer interface (like
bytearray
) and mutate_flag is true (the default), then the buffer is (in effect) passed to the underlyingioctl()
system call, the latter's return code is passed back to the calling Python, and the buffer's new contents reflect the action of theioctl()
. This is a slight simplification, because if the supplied buffer is less than 1024 bytes long it is first copied into a static buffer 1024 bytes long which is then passed toioctl()
and copied back into the supplied buffer.如果
ioctl()
调用失败,将引发OSError
异常。备注
If the type or size of arg does not match the type or size of the operation's argument (for example, if an integer is passed when a pointer is expected, or the information returned in the buffer by the operating system is larger than 1024 bytes, or the size of the mutable bytes-like object is too small), this is most likely to result in a segmentation violation or a more subtle data corruption.
举个例子:
>>> 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
将被引发 ,异常将被 errno 属性 设置为EACCES
或EAGAIN
(取决于操作系统;为便于移植,请检查这两个值)。 至少在某些系统中,只有当文件描述符指向一个已打开供写入的文件时,才能使用:const:!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()
调用可能会更好。