fcntl
—— 系统调用 fcntl
和 ioctl
¶
本模块基于文件描述符来进行文件控制和 I/O 控制。它是 Unix 系统调用 fcntl()
和 ioctl()
的接口。关于这些调用的完整描述,请参阅 Unix 手册的 fcntl(2) 和 ioctl(2) 页面。
可用性: Unix, 非 Emscripten, 非 WASI。
本模块的所有函数都接受文件描述符 fd 作为第一个参数。可以是一个整数形式的文件描述符,比如 sys.stdin.fileno()
的返回结果,或为 io.IOBase
对象,比如 sys.stdin
提供一个 fileno()
,可返回一个真正的文件描述符。
在 3.8 版本发生变更: The fcntl
module now contains F_ADD_SEALS
, F_GET_SEALS
, and
F_SEAL_*
constants for sealing of os.memfd_create()
file
descriptors.
在 3.9 版本发生变更: On macOS, the fcntl
module exposes the F_GETPATH
constant,
which obtains the path of a file from a file descriptor.
On Linux(>=3.15), the fcntl
module exposes the F_OFD_GETLK
,
F_OFD_SETLK
and F_OFD_SETLKW
constants, which are used when working
with open file description locks.
在 3.10 版本发生变更: On Linux >= 2.6.11, the fcntl
module exposes the F_GETPIPE_SZ
and
F_SETPIPE_SZ
constants, which allow to check and modify a pipe's size
respectively.
在 3.11 版本发生变更: On FreeBSD, the fcntl
module exposes the F_DUP2FD
and
F_DUP2FD_CLOEXEC
constants, which allow to duplicate a file descriptor,
the latter setting FD_CLOEXEC
flag in addition.
在 3.12 版本发生变更: 在 Linux >= 4.5 上,fcntl
模块将公开 FICLONE
和 FICLONERANGE
常量,这允许在某些系统上(例如 btrfs, OCFS2, 和 XFS)通过将一个文件引用链接到另一个文件来共享某些数据。 此行为通常被称为“写入时拷贝”。
在 3.13 版本发生变更: On Linux >= 2.6.32, the fcntl
module exposes the
F_GETOWN_EX
, F_SETOWN_EX
, F_OWNER_TID
, F_OWNER_PID
, F_OWNER_PGRP
constants, which allow to direct I/O availability signals
to a specific thread, process, or process group.
On Linux >= 4.13, the fcntl
module exposes the
F_GET_RW_HINT
, F_SET_RW_HINT
, F_GET_FILE_RW_HINT
,
F_SET_FILE_RW_HINT
, and RWH_WRITE_LIFE_*
constants, which allow
to inform the kernel about the relative expected lifetime of writes on
a given inode or via a particular open file description.
On Linux >= 5.1 and NetBSD, the fcntl
module exposes the
F_SEAL_FUTURE_WRITE
constant for use with F_ADD_SEALS
and
F_GET_SEALS
operations.
On FreeBSD, the fcntl
module exposes the F_READAHEAD
, F_ISUNIONSTACK
, and F_KINFO
constants.
On macOS and FreeBSD, the fcntl
module exposes the F_RDAHEAD
constant.
On NetBSD and AIX, the fcntl
module exposes the F_CLOSEM
constant.
On NetBSD, the fcntl
module exposes the F_MAXFD
constant.
On macOS and NetBSD, the fcntl
module exposes the F_GETNOSIGPIPE
and F_SETNOSIGPIPE
constant.
这个模块定义了以下函数:
- 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
。引发一条 auditing 事件
fcntl.fcntl
,参数为fd
、cmd
、arg
。
- fcntl.ioctl(fd, request, arg=0, mutate_flag=True)¶
本函数与
fcntl()
函数相同,只是参数的处理更加复杂。request 参数的上限是 32位。
termios
模块中包含了可用作 request 参数其他常量,名称与相关 C 头文件中定义的相同。参数 arg 可为整数、支持只读缓冲区接口的对象(如
bytes
)或支持读写缓冲区接口的对象(如bytearray
)。除了最后一种情况,其他情况下的行为都与
fcntl()
函数一样。如果传入的是个可变缓冲区,那么行为就由 mutate_flag 参数决定。
如果 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])
触发一条 auditing 事件
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 是以下值之一: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。
触发一条 审计事件
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()
调用可能会更好。