Документация Python неофициальный перевод

36.10. fcntl – Системные вызовы fcntl и ioctlfcntl – The fcntl and ioctl system calls

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

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

Модуль определяет следующие функции:

fcntl.fcntl(fd, op[, arg])

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

Если fcntl() завершается неудачей, возбуждается IOError.

fcntl.ioctl(fd, op[, arg[, mutate_flag]])

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

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

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

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

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

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

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

Если mutate_flag не указан, то начиная с Python 2.5 по умолчанию он истинен, что является изменением по сравнению с версиями 2.3 и 2.4. Указывайте аргумент явно, если переносимость между версиями является приоритетом.

Если ioctl() завершается неудачей, возбуждается исключение IOError.

Пример:

>>> 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, op)

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

Если flock() завершается неудачей, возбуждается исключение IOError.

fcntl.lockf(fd, operation[, length[, start[, whence]]])

Это, по существу, обёртка вокруг вызовов блокировки fcntl(). fd – это файловый дескриптор файла для блокировки или разблокировки, а operation – одно из следующих значений:

  • LOCK_UN – разблокировка

  • LOCK_SH – получение разделяемой блокировки

  • LOCK_EX – получение исключительной блокировки

Когда operation равно LOCK_SH или LOCK_EX, оно также может быть побитово объединено операцией ИЛИ с LOCK_NB, чтобы избежать блокировки при захвате блокировки. Если используется LOCK_NB и блокировку не удаётся захватить, возбуждается IOError, и у исключения будет атрибут errno, установленный в EACCES или EAGAIN (в зависимости от операционной системы; для переносимости проверяйте оба значения). По крайней мере, в некоторых системах LOCK_EX можно использовать только если файловый дескриптор ссылается на файл, открытый для записи.

length – это количество байт для блокировки, start – это смещение в байтах, с которого начинается блокировка, относительно whence, а whence работает так же, как в io.IOBase.seek(), а именно:

  • 0 – относительно начала файла (os.SEEK_SET)

  • 1 – относительно текущей позиции буфера (os.SEEK_CUR)

  • 2 – относительно конца файла (os.SEEK_END)

Значение по умолчанию для start – 0, что означает начало от начала файла. Значение по умолчанию для length – 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 будет содержать целочисленное значение; во втором примере она будет содержать строковое значение. Расположение структуры для переменной lockdata зависит от системы – поэтому использование вызова flock() может быть предпочтительнее.

См. также

Модуль os

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