fcntl – системные вызовы fcntl и ioctl¶fcntl – The fcntl and ioctl system calls
Этот модуль выполняет управление файлами и вводом-выводом на файловых дескрипторах. Он является интерфейсом к системным вызовам Unix fcntl() и ioctl(). Полное описание этих вызовов см. на страницах руководства Unix fcntl(2) и ioctl(2).
Все функции в этом модуле первым аргументом принимают файловый дескриптор 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, которые позволяют проверять и изменять размер канала (pipe)
соответственно.
Модуль определяет следующие функции:
-
fcntl.fcntl(fd, cmd, arg=0)¶ Выполняет операцию cmd над файловым дескриптором fd (файловые объекты, предоставляющие метод
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.
Если он ложен, изменяемость буфера игнорируется, и поведение соответствует буферу только для чтения, за исключением того, что упомянутое ограничение в 1024 байта не применяется – при условии, что передаваемый буфер имеет длину не меньше той, что операционная система хочет туда записать, всё должно работать.
Если mutate_flag истинен (по умолчанию), то буфер (фактически) передаётся базовому системному вызову
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)¶ Выполняет операцию блокировки operation для файлового дескриптора fd (также принимаются файловые объекты, предоставляющие метод
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() может быть предпочтительнее.