fcntl — Системные вызовы fcntl и ioctl


Этот модуль выполняет управление файлами и управление вводом/выводом на файловых дескрипторах. Он является интерфейсом к подпрограммам fcntl() и ioctl() Unix. Полное описание этих вызовов см. на страницах руководства по Unix fcntl(2) и ioctl(2).

Все функции в этом модуле принимают в качестве первого аргумента файловый дескриптор fd. Это может быть целочисленный дескриптор файла, например, возвращаемый функцией sys.stdin.fileno(), или объект io.IOBase, например, сам sys.stdin, который предоставляет fileno(), возвращающий настоящий дескриптор файла.

Изменено в версии 3.3: Операции в этом модуле раньше выдавали IOError, теперь они выдают OSError.

Изменено в версии 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, которые позволяют проверить и изменить размер трубы соответственно.

В Linux >= 2.6.11 модуль fcntl раскрывает константы и , которые позволяют проверить и изменить размер трубы соответственно.

fcntl.fcntl(fd, cmd, arg=0)

Выполнить операцию cmd над дескриптором файла fd (также принимаются объекты файлов, предоставляющие метод fileno()). Значения, используемые для cmd, зависят от операционной системы и доступны как константы в модуле fcntl, используя те же имена, которые используются в соответствующих заголовочных файлах языка Си. Аргумент arg может быть либо целочисленным значением, либо объектом bytes. При целочисленном значении возвращаемое значение этой функции равно целочисленному возвращаемому значению вызова C fcntl(). Когда аргументом является байт, он представляет собой двоичную структуру, например, созданную struct.pack(). Двоичные данные копируются в буфер, адрес которого передается вызову C fcntl(). Возвращаемым значением после успешного вызова является содержимое буфера, преобразованное в объект bytes. Длина возвращаемого объекта будет равна длине аргумента arg. Она ограничена 1024 байтами. Если информация, возвращаемая в буфер операционной системой, больше 1024 байт, это, скорее всего, является следствием нарушения сегментации или более тонкого повреждения данных.

Если fcntl() не срабатывает, выдается предупреждение OSError.

Вызывает auditing event fcntl.fcntl с аргументами fd, cmd, arg.

fcntl.ioctl(fd, request, arg=0, mutate_flag=True)

Эта функция идентична функции fcntl(), за исключением того, что обработка аргументов еще более сложна.

Параметр request ограничен значениями, которые могут поместиться в 32 бита. Дополнительные константы, представляющие интерес для использования в качестве аргумента request, можно найти в модуле termios под теми же именами, которые используются в соответствующих заголовочных файлах языка C.

Параметр request ограничен значениями, которые могут поместиться в 32 бита. Дополнительные константы, представляющие интерес для использования в качестве аргумента request, можно найти в модуле bytes под теми же именами, которые используются в соответствующих заголовочных файлах языка C.

Во всех случаях, кроме последнего, поведение такое же, как и для функции fcntl().

Если передается изменяемый буфер, то поведение определяется значением параметра mutate_flag.

Если это значение false, изменяемость буфера игнорируется, и поведение будет таким же, как для буфера, доступного только для чтения, за исключением упомянутого выше ограничения в 1024 байта - до тех пор, пока передаваемый вами буфер будет по крайней мере такой же длины, как то, что операционная система хочет поместить туда, все должно работать.

Если mutate_flag равен true (по умолчанию), то буфер (фактически) передается базовому системному вызову ioctl(), код возврата последнего передается обратно вызывающему Python, и новое содержимое буфера отражает действие ioctl(). Это небольшое упрощение, поскольку если длина предоставленного буфера меньше 1024 байт, он сначала копируется в статический буфер длиной 1024 байт, который затем передается в ioctl() и копируется обратно в предоставленный буфер.

Если ioctl() не удается, возникает исключение OSError.

Если mutate_flag равен true (по умолчанию), то буфер (фактически) передается базовому системному вызову , код возврата последнего передается обратно вызывающему Python, и новое содержимое буфера отражает действие . Это небольшое упрощение, поскольку если длина предоставленного буфера меньше 1024 байт, он сначала копируется в статический буфер длиной 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])

Вызывает auditing event fcntl.ioctl с аргументами fd, request, arg.

fcntl.flock(fd, operation)

Выполните операцию блокировки operation над дескриптором файла fd (также принимаются объекты файлов, предоставляющие метод fileno()). Подробности см. в руководстве по Unix flock(2). (В некоторых системах эта функция эмулируется с помощью fcntl()).

Если flock() не срабатывает, возникает исключение OSError.

Вызывает auditing event 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.

Поднимает auditing event 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() может быть лучше.

См.также

Примеры (все на системе, совместимой с SVR4):

Если флаги блокировки O_SHLOCK и O_EXLOCK присутствуют в модуле os (только на BSD), функция os.open() предоставляет альтернативу функциям lockf() и flock().

Вернуться на верх