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

fcntl – системные вызовы fcntl() и ioctl()fcntl – The fcntl() and ioctl() system calls

Платформы: Unix

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

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

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

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

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

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

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

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

Параметр op ограничен значениями, которые могут помещаться в 32 бита.

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

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

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

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

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

Пример:

>>> 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(3). (В некоторых системах эта функция эмулируется с помощью fcntl.)
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 работает как в fileobj.seek(), а именно:

  • 0 – относительно начала файла (SEEK_SET)
  • 1 – относительно текущей позиции в буфере (SEEK_CUR)
  • 2 – относительно конца файла (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, функция os.open() предоставляет более платформонезависимую альтернативу функциям lockf() и flock().