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


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

Availability: Unix, не WASI.

Все функции в этом модуле принимают в качестве первого аргумента файловый дескриптор 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, которые позволяют проверять и изменять размер трубы соответственно.

Изменено в версии 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, которые позволяют направлять сигналы доступности ввода/вывода определенному потоку, процессу или группе процессов. В 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_*, которые позволяют информировать ядро об относительном ожидаемом времени жизни записей в данный инод или через конкретное описание открытого файла. В 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)

Выполните операцию cmd над файловым дескриптором fd (принимаются также файловые объекты, предоставляющие метод fileno()). Значения, используемые для cmd, зависят от операционной системы и доступны как константы в модуле fcntl, используя те же имена, что и в соответствующих заголовочных файлах C. Аргумент arg может быть либо целым числом, либо объектом bytes. При целочисленном значении возвращаемое значение этой функции равно целочисленному возвращаемому значению вызова fcntl() на языке C. Если аргументом является байт, он представляет собой двоичную структуру, например, созданную 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.

Параметр arg может быть одним из целых чисел, объектом, поддерживающим интерфейс буфера только для чтения (например, bytes) или объектом, поддерживающим интерфейс буфера для чтения-записи (например, bytearray).

Во всех случаях, за исключением последнего, поведение соответствует поведению функции 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])

Поднимает 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 - одно из следующих значений:

fcntl.LOCK_UN

Освободите существующую блокировку.

fcntl.LOCK_SH

Получение общей блокировки.

fcntl.LOCK_EX

Приобретите эксклюзивный замок.

fcntl.LOCK_NB

Побитовое ИЛИ с любой из трех других констант LOCK_*, чтобы сделать запрос неблокирующим.

Если используется 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() может быть лучше.

См.также

Модуль os

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