fcntl — fcntl 和 ioctl 系统调用 — Python 文档
fcntl — fcntl 和 ioctl 系统调用
该模块对文件描述符执行文件控制和 I/O 控制。 它是 fcntl()
和 ioctl()
Unix 例程的接口。 有关这些调用的完整说明,请参阅 fcntl(2) 和 ioctl(2) Unix 手册页。
该模块中的所有函数都将文件描述符 fd 作为它们的第一个参数。 这可以是一个整数文件描述符,例如由 sys.stdin.fileno()
返回,或一个 io.IOBase 对象,例如 sys.stdin
本身,它提供了一个 fileno( ) 返回一个真正的文件描述符。
3.8 版更改: fcntl 模块现在包含 F_ADD_SEALS
、F_GET_SEALS
和 F_SEAL_*
常量,用于密封 os.memfd_create()[ X145X] 文件描述符。
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
常量,它们允许分别检查和修改管道的大小。
该模块定义了以下功能:
- fcntl.fcntl(fd, cmd, arg=0)
对文件描述符 fd 执行操作 cmd(也接受提供 fileno() 方法的文件对象)。 用于 cmd 的值取决于操作系统,并且在 fcntl 模块中作为常量提供,使用与相关 C 头文件中使用的名称相同的名称。 参数 arg 可以是整数值,也可以是 bytes 对象。 使用整数值,该函数的返回值是C
fcntl()
调用的整数返回值。 当参数是字节时,它表示一个二进制结构,例如 由 struct.pack() 创建。 二进制数据被复制到一个缓冲区,其地址被传递给 Cfcntl()
调用。 成功调用后的返回值是缓冲区的内容,转换为 bytes 对象。 返回对象的长度将与 arg 参数的长度相同。 这被限制为 1024 字节。 如果操作系统在缓冲区中返回的信息大于 1024 字节,这很可能会导致分段违规或更细微的数据损坏。如果
fcntl()
失败,则会引发 OSError。
- fcntl.ioctl(fd, request, arg=0, mutate_flag=True)
该函数与 fcntl() 函数相同,只是参数处理更加复杂。
request 参数仅限于可以容纳 32 位的值。 可以在 termios 模块中找到用作 request 参数的其他感兴趣的常量,其名称与相关 C 头文件中使用的名称相同。
参数 arg 可以是整数、支持只读缓冲区接口的对象(如 bytes)或支持读写缓冲区接口的对象(如 )之一字节数组)。
除了最后一种情况外,所有行为都与 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.flock(fd, operation)
对文件描述符 fd 执行锁定操作 operation(也接受提供 fileno() 方法的文件对象)。 有关详细信息,请参阅 Unix 手册 flock(2)。 (在某些系统上,使用
fcntl()
模拟此功能。)如果
flock()
失败,则会引发 OSError 异常。
- 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。
示例(均在 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() 调用可能更好。