Provided by: manpages-ru-dev_4.27.0-1_all bug

НАИМЕНОВАНИЕ

       fcntl - работа с файловым дескриптором

БИБЛИОТЕКА

       Стандартная библиотека языка C (libc, -lc)

ОБЗОР

       #include <fcntl.h>

       int fcntl(int fd, int op, ... /* arg */ );

ОПИСАНИЕ

       fcntl()  performs one of the operations described below on the open file descriptor fd.  The operation is
       determined by op.

       fcntl()   can take an optional third argument.  Whether or not this argument is required is determined by
       op.  The required argument type is indicated in parentheses after  each  op  name  (in  most  cases,  the
       required  type  is  int,  and  we  identify the argument using the name arg), or void is specified if the
       argument is not required.

       Certain of the operations below are  supported  only  since  a  particular  Linux  kernel  version.   The
       preferred method of checking whether the host kernel supports a particular operation is to invoke fcntl()
       with  the  desired op value and then test whether the call failed with EINVAL, indicating that the kernel
       does not recognize this value.

   Создание дубликата файлового дескриптора
       F_DUPFD (int)
              Создаёт  копию  файлового  дескриптора  fd,  используя  и  наименьший  доступный  номер  файлового
              дескриптора,  который  больше или равен arg. Отличие от dup2(2) в том, что там файловый дескриптор
              задаётся явно.

              При успешном выполнении этой команды, возвращается новый файловый дескриптор.

              Дополнительную информацию смотрите в dup(2).

       F_DUPFD_CLOEXEC (int; начиная с Linux 2.6.24)
              Как   F_DUPFD,   но   на   новом   файловом   дескрипторе   дополнительно   устанавливается   флаг
              закрытия-при-выполнении. Установка этого флага позволяет программам не делать дополнительный вызов
              fcntl()  с командой F_SETFD для установки флага FD_CLOEXEC. О том, зачем нужен этот флаг, смотрите
              описание O_CLOEXEC в open(2).

   Флаги файлового дескриптора
       The following operations manipulate the flags associated with a file  descriptor.   Currently,  only  one
       such  flag  is  defined:  FD_CLOEXEC,  the  close-on-exec  flag.   If the FD_CLOEXEC bit is set, the file
       descriptor will automatically be closed during a successful execve(2).  (If  the  execve(2)   fails,  the
       file  descriptor  is  left open.)  If the FD_CLOEXEC bit is not set, the file descriptor will remain open
       across an execve(2).

       F_GETFD (void)
              Вернуть (как результат функции) флаги файлового дескриптора; значение arg игнорируется.

       F_SETFD (int)
              Установить флаги файлового дескриптора согласно значению, указанному в аргументе arg.

       В многонитевых программах использование fcntl() с F_SETFD для установки флага close-on-exec  в  то  время
       как  другая нить выполняет fork(2) плюс execve(2) приводит к состязательности, что может вызвать передачу
       файлового дескриптора программе, запущенной в дочернем процессе. Смотрите обсуждение  флага  O_CLOEXEC  в
       open(2) и решение проблемы.

   Флаги состояния файла
       Каждое   описание   открытого   файла   имеет   несколько  связанных  с  ним  флагов  состояния,  которые
       инициализируются вызовом open(2) и, возможно, изменяются  затем  вызовом  fcntl().  Эти  флаги  совместно
       используются копиями файловых дескрипторов (сделанными с помощью dup(2), fcntl(F_DUPFD), fork(2) и т.д.),
       которые указывают на одно описание открытого файла.

       Эти флаги состояния и их смысл описаны в open(2).

       F_GETFL (void)
              Вернуть  (как  результат  функции)  режим  доступа  к  файлу и флаги состояния файла; значение arg
              игнорируется.

       F_SETFL (int)
              Set the file status flags to the value specified by arg.  File access  mode  (O_RDONLY,  O_WRONLY,
              O_RDWR)   and  file creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC)  in arg are ignored.
              On Linux, this  operation  can  change  only  the  O_APPEND,  O_ASYNC,  O_DIRECT,  O_NOATIME,  and
              O_NONBLOCK flags.  It is not possible to change the O_DSYNC and O_SYNC flags; see BUGS, below.

   Консультативная (advisory) блокировка
       В   Linux  реализована  обычная  («попроцессная»)  блокировка  UNIX,  стандартизованная  POSIX.  Описание
       Linux-альтернативную блокировку открытых файловых описаний с лучшей семантикой смотрите далее.

       Команды F_SETLK, F_SETLKW и F_GETLK используются  для  установки,  снятия  и  тестирования  существования
       блокировок  записей  (также  известных  как  блокировки байтового диапазона, сегмента или области файла).
       Третий аргумент, lock, является указателем на структуру, которая имеет, по крайней мере,  следующие  поля
       (в произвольном порядке):

           struct flock {
               ...
               short l_type;    /* Тип блокировки: F_RDLCK,
                                   F_WRLCK, F_UNLCK */
               short l_whence;  /* Как интерпретировать l_start:
                                   SEEK_SET, SEEK_CUR, SEEK_END */
               off_t l_start;   /* Начальное смещение блокировки */
               off_t l_len;     /* Количество блокируемых байт */
               pid_t l_pid;     /* PID процесса, блокирующего нашу блокировку
                                   (только для F_GETLK и F_OFD_GETLK) */
               ...
           };

       Поля l_whence, l_start и l_len этой структуры задают диапазон байт, который мы хотим заблокировать. Могут
       блокироваться байты за концом файла, но не перед началом файла.

       l_start — это начальное смещение для блокировки, которое интерпретируется как начало файла (если значение
       l_whence  равно SEEK_SET); как текущая позиция в файле (если значение l_whence равно SEEK_CUR); как конец
       файла  (если  значение  l_whence  равно  SEEK_END).  В  последних  двух  случаях,  l_start  может   иметь
       отрицательное значение, предоставляя смещение, которого не может указать до начала файла.

       В  l_len  задаётся  количество  байт,  которые  нужно заблокировать. Если l_len положительно, то диапазон
       блокировки начинается со l_start и кончается l_start+l_len-1 включительно. Если  в  l_len  указан  0,  то
       блокируются  все  байты  начиная  с  места, указанного l_whence и l_start и до конца файла, независимо от
       величины файла.

       POSIX.1-2001 allows (but does not require)  an implementation to support a negative l_len value; if l_len
       is negative, the interval described by lock covers bytes l_start+l_len up  to  and  including  l_start-1.
       This is supported since Linux 2.4.21 and Linux 2.5.49.

       Поле  l_type  может  быть  использовано  для  указания типа блокировки файла: чтение (F_RDLCK) или запись
       (F_WRLCK). Любое количество процессов могут удерживать блокировку на чтение  (общая  блокировка)  области
       файла,  но  только  один  процесс  может  удерживать  блокировку  на  запись  (эксклюзивная  блокировка).
       Эксклюзивная блокировка исключает все другие блокировки, как общие так и эксклюзивные. Один процесс может
       удерживать только один тип блокировки области файла; если происходит новая блокировка уже заблокированной
       области, то существующая блокировка преобразуется в новый тип  блокировки.  (Такие  преобразования  могут
       привести  к  разбиению, уменьшению или срастанию с существующей блокировкой, если диапазон байт, заданный
       для новой блокировки, неточно совпадает с диапазоном существующей блокировки.)

       F_SETLK (struct flock *)
              Установить блокировку (когда l_type равен F_RDLCK или F_WRLCK) или снять блокировку (когда  l_type
              равен   F_UNLCK)  байтов,  указанных  полями  l_whence,  l_start  и  l_len  структуры  lock.  Если
              конфликтующая  блокировка  удерживается  другим  процессом,  то данный вызов вернёт -1 и установит
              значение errno в EACCES или EAGAIN (ошибка, возвращаемая  в  этом  случае,  в  разных  реализациях
              разная, поэтому в POSIX для переносимых приложений требуется проверять оба значения).

       F_SETLKW (struct flock *)
              Как  F_SETLK,  но  если  конфликтующая  блокировка  удерживается на файле, то выполняется ожидание
              снятия этой блокировки. Если во время ожидания поступил сигнал,  то  данный  вызов  прерывается  и
              (после  возврата  из  обработчика  сигнала)  из  него происходит немедленный возврат (возвращается
              значение -1 и errno устанавливается в EINTR; см. signal(7)).

       F_GETLK (struct flock *)
              При входе в этот вызов, lock описывает блокировку, которую мы хотели бы установить на  файл.  Если
              такая  блокировка  не может быть установлена, fcntl() не устанавливает её, но возвращает F_UNLCK в
              поле l_type структуры lock и оставляет другие поля структуры неизменёнными.

              Если одна или  более  несовместимых  блокировок  мешают  установке  этой  блокировки,  то  fcntl()
              возвращает  подробности  об  одной  из  этих  блокировок в полях l_type, l_whence, l_start и l_len
              структуры lock.  Если  конфликтующая  блокировка  является  обычной  (попроцессной),  то  в  l_pid
              записывается  значение  PID  того  процесса,  который  удерживает  блокировку.  Если конфликтующая
              блокировка является блокировку открытого файлового описания, в l_pid записывается -1. Заметим, что
              возвращаемая информация может уже устареть в момент проверки вызывающим.

       Для того, чтобы установить блокировку на чтение, fd  должен  быть  открыт  на  чтение.  Для  того,  чтобы
       установить  блокировку  на запись, fd должен быть открыт на запись. Чтобы установить оба типа блокировки,
       дескриптор должен быть открыт на запись и на чтение.

       При размещении блокировок с помощью F_SETLKW, ядро  обнаруживает  взаимные  блокировки  (deadlocks),  при
       которых  два  и  более  процессов  создают  запросы на блокировку, блокируемые блокировками, удерживаемые
       другими процессами. Например, предположим, что процесс А удерживает блокировку на  запись  файла  в  байт
       100,  а  процесс  Б  удерживает  блокировку  на  запись  в байт 200. Если каждый процесс затем попытается
       заблокировать байт, который уже заблокирован другим процессом с  помощью  F_SETLKW,  то  без  обнаружения
       взаимных  блокировок  оба  процесса  останутся  заблокированными  навсегда. Когда ядро обнаруживает такие
       взаимные блокировки оно сразу же завершает одну из блокирующих блокировок с ошибкой EDEADLK;  приложение,
       встретившее  такую  ошибку,  должно  освободить  одну  из  своих  блокировок  перед попыткой восстановить
       блокировки, которые ему нужны,  позволив  другому  приложению  продолжить  работу.  Зацикленные  взаимные
       блокировки  обнаруживаются  и  для более двух процессов. Однако заметим, что есть ограничения в алгоритме
       обнаружения взаимных блокировок; смотрите ДЕФЕКТЫ.

       Также как и при снятии блокировки через явное указание F_UNLCK, блокировка автоматически снимается, когда
       процесс завершается.

       Блокировки не наследуются потомком, созданным через fork(2), но сохраняются при вызове execve(2).

       Поскольку буферизация выполняется через библиотеку stdio(3), использование блокировок с функциями в  этом
       пакете нужно избегать; вместо этих функций используйте read(2) и write(2).

       Записи  о  блокировках,  описанных  выше, связаны с процессом (в отличие от блокировках открытых файловых
       описаний, описанных далее). Это приводит к некоторым печальным последствиям:

       •  Если процесс закрывает любой файловый дескриптор, ссылающийся на файл, то освобождаются все блокировки
          процесса для этого файла, независимо от файлового дескриптора(ов), на который получена блокировка. Это
          плохо: это означает, что процесс может потерять свои блокировки на файл,  такой  как  /etc/passwd  или
          /etc/mtab, когда какой-либо причине библиотечная функция решает их открыть, прочитать и закрыть.

       •  Нити  процесса  совместно  используют  блокировки  процесса. Другими словами многонитевая программа не
          может использовать блокировку для разграничения доступа к одной области файла среди нитей.

       Блокировки открытых файловых описаний решают обе эти проблемы.

   Блокировки открытых файловых описаний (не POSIX)
       Блокировки открытых файловых описаний являются консультативными блокировками диапазона байт, чьё действие
       почти идентично обычным блокировкам, описанным выше. Данный тип блокировок есть только в Linux и доступен
       с версии 3.15 (есть предложение в  Austin  Group  включить  данный  тип  блокировки  в  следующую  версию
       POSIX.1). Описание открытых файловых описаний смотрите в open(2).

       Принципиальное  различие между двумя типами блокировок в том, что обычные блокировки связаны с процессом,
       а блокировки открытых файловых описаний связаны с открытым файловым описанием, для которого они  получены
       (очень  похоже  на  блокировки,  получаемые с помощью flock(2). В следствие этого (и в отличие от обычных
       консультативных блокировок), блокировки  открытых  файловых  описаний  наследуются  при  fork(2)  (и  при
       clone(2)  с CLONE_FILES), и освобождаются только автоматически при последнем закрытии открытого файлового
       описания, а не при любом закрытии файла.

       Конфликт комбинаций блокировок (блокировка чтения и блокировка записи или  две  блокировки  записи),  при
       котором  одна  блокировка  —  открытое файловое описание, а другая — обычная блокировка, конфликтуют даже
       когда они запрашиваются одним процессом для одного и того же файлового дескриптора.

       Блокировки открытых файловых описаний, полученные для одного и того же файлового  описания  (т.  е.,  для
       одного  и  того  же  файлового дескриптора или его копии, созданной в результате fork(2), dup(2), fcntl()
       F_DUPFD и т. п.), всегда совместимы: если новая блокировка помещается на уже заблокированную область,  то
       существующая  блокировка  преобразуется  в блокировку нового типа (такие преобразования могут приводить к
       разделению, сокращению или объединению существующей блокировки, как описывалось ранее).

       С другой стороны, блокировки открытых файловых описаний могут конфликтовать  друг  с  другом,  когда  они
       запрашиваются  через  разные  открытые  файловые  описания. То есть, нити в многонитевых программах могут
       использовать блокировки открытых файловых описаний  для  синхронизации  доступа  к  области  файла,  если
       каждая  нить  выполняет  отдельный вызов open(2) на файл и применяет блокировки для получаемого файлового
       дескриптора.

       As with traditional advisory locks, the third argument to  fcntl(),  lock,  is  a  pointer  to  an  flock
       structure.   By  contrast with traditional record locks, the l_pid field of that structure must be set to
       zero when using the operations described below.

       The operations for working with open file description locks are analogous to those used with  traditional
       locks:

       F_OFD_SETLK (struct flock *)
              Установить  блокировку  открытого  файлового описания (когда l_type равен F_RDLCK или F_WRLCK) или
              снять блокировку открытого файлового описания  (когда  l_type  равен  F_UNLCK)  байтов,  указанных
              полями l_whence, l_start и l_len структуры lock. Если конфликтующая блокировка удерживается другим
              процессом, то данный вызов вернёт -1 и установит значение errno в EAGAIN.

       F_OFD_SETLKW (struct flock *)
              Как  F_OFD_SETLK,  но если конфликтующая блокировка удерживается на файле, то выполняется ожидание
              снятия этой блокировки. Если во время ожидания поступил сигнал,  то  данный  вызов  прерывается  и
              (после  возврата  из  обработчика  сигнала)  из  него происходит немедленный возврат (возвращается
              значение -1 и errno устанавливается в EINTR; см. signal(7)).

       F_OFD_GETLK (struct flock *)
              В начала данного вызова значение lock описывает блокировку открытого файлового  описания,  которую
              мы  бы  хотели  создать  на  файле.  Если блокировка возможна, то в действительности fcntl() её не
              создаёт, а возвращает F_UNLCK в поле l_type у lock, оставляя остальные поля неизменными. Если есть
              одна или  более  несовместимых  блокировок,  препятствующих  получению,  то  в  lock  возвращается
              подробная информация об этих блокировках, как описывалось выше для F_GETLK.

       В  текущей  реализации  для  блокировок  открытых  файловых  описаний  обнаружение взаимных блокировок не
       выполняется (в этом отличие от попроцессных блокировок, для которых ядро выполняет  обнаружение  взаимных
       блокировок).

   Обязательная (mandatory) блокировка
       Warning:  the Linux implementation of mandatory locking is unreliable.  See BUGS below.  Because of these
       bugs, and the fact that the feature is believed to be little used, since Linux 4.5, mandatory locking has
       been made an optional feature, governed by a configuration option (CONFIG_MANDATORY_FILE_LOCKING).   This
       feature is no longer supported at all in Linux 5.15 and above.

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

       Оба  типа  блокировки могут быть также обязательными. Если процесс пытается получить несовместимый доступ
       (например, read(2) и write(2))  к  области  файла,  на  которую  установлена  несовместимая  обязательная
       блокировка,  то  результат  зависит  от состояния флага O_NONBLOCK в описании этого открытого файла. Если
       флаг O_NONBLOCK не установлен, то системный вызов блокируется до удаления блокировки или преобразуется  в
       режим,  который  совместим  с доступом. Если флаг O_NONBLOCK установлен, то системный вызов завершается с
       ошибкой EAGAIN.

       Чтобы использовать обязательные блокировки, обязательное блокирование должно  быть  включено  в  файловой
       системе,  содержащей  файл,  и  на самом файле. Обязательное блокирование включается в файловой системе с
       помощью параметра «-o mand» команды mount(8) или с помощью флага  MS_MANDLOCK  в  mount(2).  Обязательное
       блокирование  включается  на  файле  посредством  отключения  права  исполнения  группе и установкой бита
       set-group-ID (см. chmod(1) и chmod(2)).

       Обязательная блокировка не описана в POSIX. В некоторых других  системах  обязательная  блокировка  также
       поддерживается, хотя процесс её создания различен.

   Потерянные блокировки
       При  получении  консультативной блокировки на сетевой файловой системе, например NFS, возможна её потеря.
       Это может случиться из-за административного  действия  или  сетевой  проблемы  (т.  е.,  потеря  связи  с
       сервером), которая длится достаточно долго для того, чтобы сервер посчитал клиента за неработающего.

       Когда  файловая  система  определяет,  что  блокировка потеряна, последующие запросы read(2) или write(2)
       могут завершиться ошибкой EIO. Эта ошибка будет повторяться до тех пор, пока блокировка не  удалится  или
       не закроется файловый дескриптор. Начиная с Linux 3.12, так работает, по крайней мере, NFSv4 (включая все
       предыдущие версии).

       Некоторые  версии  UNIX  при  таких  обстоятельствах  посылают  сигнал (SIGLOST). В Linux такой сигнал не
       определён и не существует какого-либо асинхронного уведомления о потере блокировки.

   Управление сигналами
       Для управления сигналами доступности ввода/вывода используются команды F_GETOWN,  F_SETOWN,  F_GETOWN_EX,
       F_SETOWN_EX, F_GETSIG и F_SETSIG:

       F_GETOWN (void)
              Return  (as the function result)  the process ID or process group ID currently receiving SIGIO and
              SIGURG signals for events on file descriptor fd.  Process IDs are  returned  as  positive  values;
              process group IDs are returned as negative values (but see BUGS below).  arg is ignored.

       F_SETOWN (int)
              Установить  идентификатор  процесса  или  группы процесса, которые будут принимать сигналы SIGIO и
              SIGURG для событий  на  файловом  дескрипторе  fd.  Идентификатор  целевого  процесса  или  группы
              процессов  задаётся  в  аргументе  arg.  Идентификатор  процесса  задаётся  положительным  числом,
              идентификатор группы задаётся отрицательным числом. Обычно, вызывающий  процесс  указывает  самого
              себя в качестве владельца (то есть в arg указывается результат getpid(2)).

              As  well  as  setting the file descriptor owner, one must also enable generation of signals on the
              file descriptor.  This is done by using the fcntl()  F_SETFL operation to  set  the  O_ASYNC  file
              status flag on the file descriptor.  Subsequently, a SIGIO signal is sent whenever input or output
              becomes  possible  on  the  file descriptor.  The fcntl() F_SETSIG operation can be used to obtain
              delivery of a signal other than SIGIO.

              Отправка сигнала процессу-владельцу (группе), указанному с помощью F_SETOWN —  такая  же  проверка
              прав,  как  описано  в  kill(2),  где  посылающий  процесс один из тех, который может пользоваться
              F_SETOWN (но смотрите  раздел  ДЕФЕКТЫ  далее).  Если  проверка  не  проходит,  то  сигнал  просто
              отбрасывается.  Замечание:  операция  F_SETOWN  сохраняет  мандаты  вызывающего  на  момент вызова
              fcntl(), и эти сохранённые мандаты затем используются при проверке прав.

              Если файловый дескриптор fd указывает на сокет, то по команде F_SETOWN для него  также  выбирается
              получатель  сигналов  SIGURG,  которые  доставляются, когда на сокет поступают внеполосные данные.
              (SIGURG посылается во всех ситуациях,  когда  вызов  select(2)  говорит,  что  сокет  находится  в
              состоянии "исключительной ситуации".)

              The following was true in Linux 2.6.x up to and including Linux 2.6.11:

                     Если  для  F_SETSIG  передаётся  ненулевое  значение  в  многонитевой процесс, работающий с
                     библиотекой  нитей  (например,  NPTL),  которая  обеспечивает  поддержку  групп  нитей,  то
                     положительное  значение,  переданное  F_SETOWN,  имеет  другой  смысл:  вместо  указания ID
                     процесса, описывающего весь процесс, она является ID нити, указывающим на определённую нить
                     процесса. Поэтому  может  понадобиться  передать  в  F_SETOWN  результат  gettid(2),  а  не
                     getpid(2),  чтобы  получить  правильный  результат при использовании F_SETSIG. (В имеющихся
                     реализациях Linux ID главной нити совпадает с ID процесса. Это означает, что в программе  с
                     одной нитью можно использовать любой вызов, gettid(2) или getpid(2), в этом случае.) Однако
                     заметим,  что  утверждения  этого  абзаца  не применимы к сигналу SIGURG, генерируемому для
                     внеполосных данных сокета: этот сигнал всегда посылается или процессу или группе процессов,
                     в зависимости от значения, указанного для F_SETOWN.

              Описанное выше поведение было случайно удалено из Linux 2.6.12, и так и не восстановлено.  Начиная
              с  Linux  2.6.32  используйте  F_SETOWN_EX при назначении сигналов SIGIO и SIGURG для определённой
              нити.

       F_GETOWN_EX (struct f_owner_ex *) (начиная с Linux 2.6.32)
              Получить настройки владения  текущим  файловым  дескриптором,  установленные  предыдущей  командой
              F_SETOWN_EX. Информация возвращается в структуре, указанной в arg, которая имеет следующий вид:

                  struct f_owner_ex {
                      int   type;
                      pid_t pid;
                  };

              Поле  type  будет  равно:  F_OWNER_TID,  F_OWNER_PID  или  F_OWNER_PGRP.  Значением поля pid будет
              положительное целое, представляющее ID нити, ID процесса  или  ID  группы  процессов.  Подробности
              смотрите в описании F_SETOWN_EX.

       F_SETOWN_EX (struct f_owner_ex *) (начиная с Linux 2.6.32)
              Эта  команда  выполняет  задачу,  подобную  F_SETOWN.  Она позволяет вызывающему назначить сигналы
              доступности ввода-вывода определённой нити, процессу или группе  процессов.  Вызывающий  указывает
              приёмник  сигналов  в  arg, выражаемый указателем на структуру f_owner_ex. Поле type имеет одно из
              следующих значений, которое определяет чем считать pid:

              F_OWNER_TID
                     Посылать сигнал нити, чей ID (значение, возвращаемое вызовом clone(2) или gettid(2)) указан
                     в pid.

              F_OWNER_PID
                     Посылать сигнал процессу, чей ID указан в pid.

              F_OWNER_PGRP
                     Посылать сигнал группе процессов, чей ID указан в pid. (Заметим, что в отличие от F_SETOWN,
                     ID группы процессов здесь задаётся как положительное значение.)

       F_GETSIG (void)
              Получить (как результат функции) сигнал, посылаемый, когда становится возможным  ввод  или  вывод.
              Значение  0 означает сигнал SIGIO. Любое другое значение (включая SIGIO) является другим сигналом,
              и в этом случае для обработчика сигнала доступна дополнительная информация, если он был установлен
              с SA_SIGINFO. Аргумент arg игнорируется.

       F_SETSIG (int)
              Установить сигнал, который будет посылаться когда станет возможен  ввод  или  вывод,  в  значение,
              указанное  в  arg.  Значение  0 означает сигнал по умолчанию SIGIO. Любое другое значение (включая
              SIGIO) является другим сигналом, и в этом случае, для обработчика сигнала доступна  дополнительная
              информация, если он был установлен с SA_SIGINFO.

              В  случае  использования  F_SETSIG  с  ненулевым значением и установкой SA_SIGINFO для обработчика
              сигнала  (см.  sigaction(2))  обработчику  передаётся   дополнительная   информация   о   событиях
              ввода/вывода в структуре siginfo_t. Если поле si_code показывает, что источник — SI_SIGIO, то поле
              si_fd  содержит  файловый дескриптор, ассоциированный с событием. В противном случае не существует
              никакого механизма, чтобы сообщить с каким файловым дескриптором связан полученный  сигнал,  и  вы
              должны  использовать  обычные  механизмы (select(2), poll(2), read(2) с установленным O_NONBLOCK и
              т.д.), чтобы определить какой файловый дескриптор доступен для ввода/вывода.

              Заметим, что файловый дескриптор, предоставляемый в si_fd, тот же,  что  указывался  при  операции
              F_SETSIG.  Это  может  привести к редкой  тупиковой ситуации. Если с файлового дескриптора делался
              дубль (dup(2) или подобным  вызовом),  и  оригинальный  файловый  дескриптор  закрыт,  то  события
              ввода-вывода  будут  продолжать  генерироваться,  но  поле  si_fd будет содержать номер теперь уже
              закрытого файлового дескриптора.

              При выборе сигнала реального времени (значение >= SIGRTMIN) в очередь может добавляться  несколько
              событий ввода-вывода с одинаковыми номерами сигналов (размер очереди зависит от доступной памяти).
              Дополнительная  информация  будет  доступна  как  описано выше, если для обработчика сигнала будет
              установлено SA_SIGINFO.

              Заметим, что в  Linux  есть  предел  на  количество  сигналов  реального  времени,  которые  могут
              находиться  в  очереди  процесса  (см. getrlimit(2) и signal(7)), и если этот предел достигнут, то
              ядро изменяет пункт доставки SIGIO, и этот сигнал доставляется  всему  процессу,  а  не  указанной
              нити.

       Используя  эти механизмы, программа может реализовать полностью асинхронный ввод-вывод почти не используя
       в своей работе select(2) или poll(2).

       The use of O_ASYNC is specific to BSD and Linux.  The only use of  F_GETOWN  and  F_SETOWN  specified  in
       POSIX.1  is  in  conjunction  with  the use of the SIGURG signal on sockets.  (POSIX does not specify the
       SIGIO  signal.)   F_GETOWN_EX,  F_SETOWN_EX,  F_GETSIG,  and  F_SETSIG  are  Linux-specific.   POSIX  has
       asynchronous  I/O  and  the aio_sigevent structure to achieve similar things; these are also available in
       Linux as part of the GNU C Library (glibc).

   Аренда
       Команды F_SETLEASE и F_GETLEASE (в Linux 2.4 и выше) используются для установки новой и получения текущей
       аренды открытого описания файла, на который указывает файловый дескриптор fd. Аренда файла  предоставляет
       механизм,  посредством которого процесс, который удерживает аренду («арендатор»), уведомляется (отправкой
       сигнала), когда процесс («нарушитель аренды») пытается выполнить вызов open(2) или truncate(2)  на  файл,
       указанный в этом файловом дескрипторе.

       F_SETLEASE (int)
              Установить или удалить аренду файла, в соответствии со значениями, указываемыми в arg:

              F_RDLCK
                     Установить  аренду чтения. Это приведёт к генерации уведомления вызывающего процесса, когда
                     файл открывается для записи или усечения. Аренда  чтения  может  быть  выделена  только  на
                     файловый дескриптор, открытый только на чтение.

              F_WRLCK
                     Установить  аренду записи. Это приведёт к генерации уведомления вызывающего процесса, когда
                     файл открывается для чтения или записи или выполняется его усечение.  Аренда  записи  может
                     быть  установлена  на  файл,  только  если  этот  файл  не  имеет  других открытых файловых
                     дескрипторов.

              F_UNLCK
                     Удалить аренду с указанного файла.

       Аренды ассоциируются с открытым файловым описанием (см. open(2)). Это значит, что дублированные  файловые
       дескрипторы  (созданные,  например,  fork(2)  или  dup(2)) указывают на одну и ту же аренду, и эта аренда
       может изменяться или освобождаться через любой из этих дескрипторов. Более того, аренда освобождается или
       через явную команду F_UNLCK на любом из этих дублированных  файловых  дескрипторов,  или  когда  все  эти
       файловые дескрипторы будут закрыты.

       Аренды  могут  быть  выданы  только  на  обычные файлы. Непривилегированный процесс может получить аренду
       только на файл, чей UID (владельца) совпадает с UID на файловой  системе  процесса.  Процесс  с  мандатом
       CAP_LEASE может получить аренду на любые файлы.

       F_GETLEASE (void)
              Узнать  какой  тип  аренды  ассоциирован с файловым дескриптором fd; возвращается одно из значений
              F_RDLCK, F_WRLCK или F_UNLCK, соответственно означающих аренду на чтение, запись  или  что  аренды
              нет. Аргумент arg игнорируется.

       When  a  process  (the  "lease breaker") performs an open(2)  or truncate(2)  that conflicts with a lease
       established via F_SETLEASE, the system call is blocked by the kernel and the kernel  notifies  the  lease
       holder  by  sending  it  a signal (SIGIO by default).  The lease holder should respond to receipt of this
       signal by doing whatever cleanup is required in preparation for  the  file  to  be  accessed  by  another
       process  (e.g.,  flushing  cached  buffers)  and  then  either remove or downgrade its lease.  A lease is
       removed by performing an F_SETLEASE operation specifying arg as F_UNLCK.  If the lease  holder  currently
       holds  a  write  lease  on  the  file,  and the lease breaker is opening the file for reading, then it is
       sufficient for the lease holder to downgrade the lease to a read lease.  This is done  by  performing  an
       F_SETLEASE operation specifying arg as F_RDLCK.

       Если  арендатор  не  освободит  аренду  или  не снизит условия в течении определённого количества секунд,
       указанного в файле /proc/sys/fs/lease-break-time, то ядро принудительно удалит или снизит условия  аренды
       для арендатора.

       После  того,  как  был  начат разрыв аренды, F_GETLEASE возвращает тип назначения аренды (или F_RDLCK или
       F_UNLCK, в зависимости от необходимости совместимости с нарушителем аренды) до тех  пор,  пока  держатель
       аренды  добровольно  не отдаст или не удалит аренду или ядро принудительно не сделает это после истечения
       таймера разрыва аренды.

       После того как аренда снята держателем аренды или принудительно удалена и снижены условия, и предполагая,
       что нарушитель аренды не  выполнял  неблокирующий  системный  вызов,  ядро  позволяет  продолжить  работу
       системного вызова нарушителя аренды.

       Если  нарушитель  аренды, заблокированный в open(2) или truncate(2), прерывается обработчиком сигнала, то
       системный вызов завершается неудачно с ошибкой EINTR, но другие шаги по-прежнему выполняются как  описано
       ранее.  Если  нарушитель аренды завершается по сигналу будучи блокированным в open(2) или truncate(2), то
       другие шаги по-прежнему выполняются как описано ранее. Если нарушитель аренды указал флаг O_NONBLOCK  при
       вызове  open(2),  то  вызов  немедленно  завершается  неудачей  с  ошибкой  EWOULDBLOCK,  но  другие шаги
       по-прежнему выполняются как описано ранее.

       The default signal used to notify the lease holder is SIGIO, but this can be changed using  the  F_SETSIG
       operation  to  fcntl().  If a F_SETSIG operation is performed (even one specifying SIGIO), and the signal
       handler is established using SA_SIGINFO, then the handler will  receive  a  siginfo_t  structure  as  its
       second  argument,  and  the si_fd field of this argument will hold the file descriptor of the leased file
       that has been accessed by another process.  (This is useful if the caller holds leases  against  multiple
       files.)

   Уведомления об изменении файла и каталога (dnotify)
       F_NOTIFY (int)
              (Начиная  с Linux 2.4) Уведомлять при смене каталога, на который указывает fd или когда изменились
              файлы, которые в нём содержатся. События, о наступлении которых делается уведомление,  задаются  в
              аргументе  arg,  который  является  битовой  маской,  получаемой  сложением  (OR) одного или более
              следующих бит:

              DN_ACCESS
                     Был произведён доступ к файлу (read(2), pread(2), readv(2) и подобные).
              DN_MODIFY
                     Файл был изменён (write(2), pwrite(2), writev(2), truncate(2), ftruncate(2) и подобные).
              DN_CREATE
                     Файл был создан (open(2), creat(2), mknod(2), mkdir(2), link(2),  symlink(2),  rename(2)  в
                     этом каталоге).
              DN_DELETE
                     Файл был удалён (unlink(2), rename(2) в другой каталог, rmdir(2)).
              DN_RENAME
                     Файл был переименован внутри каталога (rename(2)).
              DN_ATTRIB
                     У файла были изменены атрибуты (chown(2), chmod(2), utime(2), utimensat(2) и подобные).

              (Чтобы  получить эти определения, нужно задать макрос тестирования свойств _GNU_SOURCE перед всеми
              остальными заголовочными файлами.)

              Уведомления  об  изменении   состояния   каталога   обычно   однократные   и   приложение   должно
              перерегистрировать установку уведомлений, чтобы и дальше получать их. Однако, если в аргумент arg,
              добавить DN_MULTISHOT, то уведомления будут приходить до тех пор, пока не будут явно отменены.

              Серии  запросов  F_NOTIFY  добавляются  к событиям в arg, которые уже установлены. Чтобы выключить
              уведомления всех событий, выполните вызов F_NOTIFY, указав 0 в arg.

              Notification occurs via delivery of a signal.  The default  signal  is  SIGIO,  but  this  can  be
              changed  using  the  F_SETSIG  operation  to  fcntl().   (Note that SIGIO is one of the nonqueuing
              standard signals; switching to the use of a real-time signal means that multiple notifications can
              be queued to the process.)  In the latter case, the signal handler receives a siginfo_t  structure
              as  its  second argument (if the handler was established using SA_SIGINFO)  and the si_fd field of
              this structure contains  the  file  descriptor  which  generated  the  notification  (useful  when
              establishing notification on multiple directories).

              Кроме  того,  когда  используется  DN_MULTISHOT, для уведомлений должен бы быть использован сигнал
              реального времени, так что множественные уведомления могут быть поставлены в очередь.

              NOTE: New applications should use the inotify interface  (available  since  Linux  2.6.13),  which
              provides  a  much  superior  interface  for  obtaining  notifications  of  filesystem events.  See
              inotify(7).

   Изменение ёмкости канала
       F_SETPIPE_SZ (int; начиная с Linux 2.6.35)
              Изменяет ёмкость канала, на который указывает  fd;  она  становится  равной  не  менее  arg  байт.
              Непривилегированный  процесс  может  задать  ёмкость  канала  любого  значения,  начиная с размера
              системной страницы до ограничения, заданного в /proc/sys/fs/pipe-max-size (смотрите proc(5)).  При
              задании  ёмкости  меньше размера страницы, она будет без ошибок округлена до размера страницы. При
              задании    непривилегированным    процессом    ёмкости    канала     больше     ограничения     из
              /proc/sys/fs/pipe-max-size приведёт к ошибке EPERM; привилегированный процесс (с CAP_SYS_RESOURCE)
              может превысить это ограничение.

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

              Попытка  задать  ёмкость  канала  меньшую  размера  буферного пространства, используемого в данный
              момент для хранения данных в канале приводит к ошибке EBUSY.

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

       F_GETPIPE_SZ (void; начиная с Linux 2.6.35)
              Возвращает (как результат функции) ёмкость канала, указываемого fd.

   Опечатывание файла (file sealing)
       Опечатывание файла позволяет ограничить набор выполняемых над файлом операций. Любая операция  с  файлом,
       попавшая  в  набор  опечатанных,  завершается с ошибкой EPERM. Набор печатей по умолчанию зависит от типа
       файла, к которому он применяется и  файловой  системы.  Описание  опечатывания  файла,  предназначение  и
       примеры кода смотрите в memfd_create(2).

       В   настоящее   время  опечатывание  файла  может  применяться  к  файловому  дескриптору,  возвращаемому
       memfd_create(2) (если был указан MFD_ALLOW_SEALING). В других файловых  системах  все  операции  fcntl(),
       относящиеся к печатям, возвращают EINVAL.

       Печати  (seals)  —  свойство inode. То есть все открытые файловые дескрипторы, указывающие на один inode,
       имеют общий набор печатей. Кроме этого, печати нельзя удалять, можно только добавлять.

       F_ADD_SEALS (int; начиная с Linux 3.17)
              Добавляет печати из значения битовой маски  arg  в  набор  печатей  inode,  на  которую  ссылается
              файловый  дескриптор fd. Печати из набора нельзя удалить. После успешного выполнения, печати сразу
              же учитываются ядром. Если в текущий набор печатей входит F_SEAL_SEAL (смотрите  далее),  то  этот
              вызов завершается с ошибкой EPERM. Добавление уже установленной печати ни к чему не приводит, если
              ещё не указана F_SEAL_SEAL. Чтобы разместить печать файловый дескриптор fd должен быть доступен на
              запись.

       F_GET_SEALS (void; начиная с Linux 3.17)
              Возвращает  (в виде результата функции) текущий набор печатей inode, на которую указывает fd. Если
              печатей нет, возвращается 0. Если файл не поддерживает опечатывание, то возвращается  -1  и  errno
              присваивается EINVAL.

       Доступны следующие печати:

       F_SEAL_SEAL
              Если печать установлена, то последующий вызов fcntl() с F_ADD_SEALS завершится ошибкой EPERM. Таки
              образом, данная печать предотвращает изменения самого набора печатей. Если начальный набор печатей
              файла содержит F_SEAL_SEAL, то он является постоянным и неизменяемым.

       F_SEAL_SHRINK
              Если  эта  печать  установлена,  то  нельзя уменьшить размер файла. Она влияет на open(2) с флагом
              O_TRUNC, а также на truncate(2)  и  ftruncate(2).  Эти  вызовы  завершаются  ошибкой  EPERM,  если
              пытаются уменьшить файл. Увеличение размера файла по-прежнему возможно.

       F_SEAL_GROW
              Если  эта  печать  установлена, то нельзя увеличить размер файла. Она влияет на write(2) за концом
              файла, truncate(2), ftruncate(2) и  fallocate(2).  Эти  вызовы  завершаются  ошибкой  EPERM,  если
              пытаются увеличить файл. Уменьшение размера файла по-прежнему возможно.

       F_SEAL_WRITE
              Если  эта  печать  установлена,  то  нельзя изменить содержимое файла. Заметим, что уменьшение или
              увеличение файла по-прежнему возможно. То есть данная печать, обычно, используется в комбинации  с
              одной  из  этих  печатей.  Данная  печать  влияет  на  write(2)  и  fallocate(2) (только для флага
              FALLOC_FL_PUNCH_HOLE). Эти вызовы завершаются ошибкой EPERM. Кроме этого,  попытка  создать  новое
              общее, доступное на запись отображение через mmap(2) также завершится ошибкой EPERM.

              Использование  операции  F_ADD_SEALS  для  установки  F_SEAL_WRITE завершается ошибкой EBUSY, если
              существует доступное на запись общее отображение. Такие  отображения  должны  быть  удалены  перед
              добавлением  данной  печати.  Кроме  этого,  если  у  файла  есть  асинхронные операции, ожидающие
              ввода-вывода (io_submit(2)), то все отложенные операции записи будут отброшены.

       F_SEAL_FUTURE_WRITE (начиная с Linux 5.1)
              The effect of this seal is similar to F_SEAL_WRITE, but the contents of  the  file  can  still  be
              modified  via shared writable mappings that were created prior to the seal being set.  Any attempt
              to create a new writable mapping on the file via mmap(2)  will  fail  with  EPERM.   Likewise,  an
              attempt to write to the file via write(2)  will fail with EPERM.

              Using  this  seal,  one  process  can  create a memory buffer that it can continue to modify while
              sharing that buffer on a "read-only" basis with other processes.

   Подсказки чтения/записи файла
       Подсказки срока службы записи можно использовать для уведомления ядра  об  относительно  ожидаемом  сроке
       службы  записи  заданной  иноды  и открытого файлового описания (об открытых файловых описаниях читайте в
       open(2)). В этом контексте термин «срок службы записи» (write lifetime) означает ожидаемое время, которое
       будут существовать данные на носителе до их перезаписи или стирания.

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

       Следующие операции могут применяться к файловому дескриптору fd:

       F_GET_RW_HINT (uint64_t *; начиная с Linux 4.13)
              Возвращает значение подсказки чтения/записи, связанной с инодой, на которую указывает fd.

       F_SET_RW_HINT (uint64_t *; начиная с Linux 4.13)
              Изменяет  значение  подсказки  чтения/записи,  связанной с инодой, на которую указывает fd. Данная
              подсказка действует до  тех  пор,  пока  не  будет  явно  изменена  или  не  будет  размонтирована
              нижележащая файловая система.

       F_GET_FILE_RW_HINT (uint64_t *; начиная с Linux 4.13)
              Возвращает  значение  подсказки чтения/записи, связанной с открытым файловым описанием, на которое
              указывает fd.

       F_SET_FILE_RW_HINT (uint64_t *; начиная с Linux 4.13)
              Изменяет значение подсказки чтения/записи, связанной с открытым  файловым  описанием,  на  которое
              указывает fd.

       Если  открытому  файловому  описанию  не  была назначена подсказка чтения/записи, то будет использоваться
       значение (если есть), назначенное иноде.

       Начиная с Linux 4.13, действуют следующие подсказки чтения/записи:

       RWH_WRITE_LIFE_NOT_SET
              Подсказка не задана. Это значение по умолчанию.

       RWH_WRITE_LIFE_NONE
              Срока службы записи, связанного с этим файлом или инодой, не задано.

       RWH_WRITE_LIFE_SHORT
              Ожидается, что данные, записанные в эту иноду или через открытое файловое  описание,  будут  иметь
              короткий срок службы.

       RWH_WRITE_LIFE_MEDIUM
              Ожидается,  что  данные,  записанные в эту иноду или через открытое файловое описание, будут иметь
              срок службы длиннее, чем данные, записанные с RWH_WRITE_LIFE_SHORT.

       RWH_WRITE_LIFE_LONG
              Ожидается, что данные, записанные в эту иноду или через открытое файловое  описание,  будут  иметь
              срок службы длиннее, чем данные, записанные с RWH_WRITE_LIFE_MEDIUM.

       RWH_WRITE_LIFE_EXTREME
              Ожидается,  что  данные,  записанные в эту иноду или через открытое файловое описание, будут иметь
              срок службы длиннее, чем данные, записанные с RWH_WRITE_LIFE_LONG.

       Все подсказки записи соотносятся друг с другом и нет отдельного абсолютного смысла им предписываемого.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       При успешном выполнении возвращаемое значение зависит от используемой команды:

       F_DUPFD
              Новый файловый дескриптор.

       F_GETFD
              Значение флагов файлового дескриптора.

       F_GETFL
              Значение флагов состояния файла.

       F_GETLEASE
              Тип аренды, установленной на файлом дескрипторе.

       F_GETOWN
              Значение, представляющее собой владельца файлового дескриптора.

       F_GETSIG
              Значение  сигнала,  посылаемого  когда  становится  возможным  чтение  или  запись  или  ноль  для
              традиционного поведения SIGIO.

       F_GETPIPE_SZ
       F_SETPIPE_SZ
              Ёмкость канала.

       F_GET_SEALS
              Битовая маска, описывающая печати inode, на которую указывает fd.

       Остальные операции
              Ноль.

       В случае ошибки возвращается -1, а errno устанавливается в значение ошибки.

ОШИБКИ

       EACCES или EAGAIN
              Операция запрещена блокировками, которые удерживаются другими процессами.

       EAGAIN Операция запрещена, потому что файл отображается в память другим процессом.

       EBADF  Значение fd не является открытым файловым дескриптором.

       EBADF  op  is  F_SETLK  or F_SETLKW and the file descriptor open mode doesn't match with the type of lock
              requested.

       EBUSY  op is F_SETPIPE_SZ and the new pipe capacity specified in arg is smaller than the amount of buffer
              space currently used to store data in the pipe.

       EBUSY  op is F_ADD_SEALS, arg includes F_SEAL_WRITE, and there exists a writable, shared mapping  on  the
              file referred to by fd.

       EDEADLK
              It was detected that the specified F_SETLKW operation would cause a deadlock.

       EFAULT Значение lock находится за пределами доступного адресного пространства.

       EINTR  op is F_SETLKW or F_OFD_SETLKW and the operation was interrupted by a signal; see signal(7).

       EINTR  op is F_GETLK, F_SETLK, F_OFD_GETLK, or F_OFD_SETLK, and the operation was interrupted by a signal
              before  the  lock  was checked or acquired.  Most likely when locking a remote file (e.g., locking
              over NFS), but can sometimes happen locally.

       EINVAL The value specified in op is not recognized by this kernel.

       EINVAL op is F_ADD_SEALS and arg includes an unrecognized sealing bit.

       EINVAL op is F_ADD_SEALS or F_GET_SEALS and the filesystem containing the inode referred to  by  fd  does
              not support sealing.

       EINVAL op  is  F_DUPFD  and  arg  is  negative  or  is  greater than the maximum allowable value (see the
              discussion of RLIMIT_NOFILE in getrlimit(2)).

       EINVAL op is F_SETSIG and arg is not an allowable signal number.

       EINVAL op is F_OFD_SETLK, F_OFD_SETLKW, or F_OFD_GETLK, and l_pid was not specified as zero.

       EMFILE op is F_DUPFD and the per-process limit on the number of open file descriptors has been reached.

       ENOLCK Открыто слишком много блокировок сегментов, таблица  блокировок  заполнена  или  ошибка  протокола
              удалённой блокировки (например, при блокировке через NFS).

       ENOTDIR
              F_NOTIFY was specified in op, but fd does not refer to a directory.

       EPERM  op is F_SETPIPE_SZ and the soft or hard user pipe limit has been reached; see pipe(7).

       EPERM  Попытка сбросить флаг O_APPEND на файле, который открыт с атрибутом только для добавления.

       EPERM  op  was  F_ADD_SEALS,  but  fd  was  not  open for writing or the current set of seals on the file
              already includes F_SEAL_SEAL.

СТАНДАРТЫ

       POSIX.1-2008.

       Команды F_GETOWN_EX, F_SETOWN_EX, F_SETPIPE_SZ, F_GETPIPE_SZ, F_GETSIG, F_SETSIG, F_NOTIFY, F_GETLEASE  и
       F_SETLEASE есть только в Linux. Для задействования этих определений определите макрос _GNU_SOURCE.

       Значения  F_OFD_SETLK,  F_OFD_SETLKW  и  F_OFD_GETLK  есть только в Linux (и для получения их определений
       нужно определить _GNU_SOURCE), но ведётся работа по их включению в следующую версию POSIX.1.

       Значения F_ADD_SEALS и F_GET_SEALS есть только в Linux.

ИСТОРИЯ

       SVr4, 4.3BSD, POSIX.1-2001.

       Only the operations F_DUPFD, F_GETFD, F_SETFD, F_GETFL,  F_SETFL,  F_GETLK,  F_SETLK,  and  F_SETLKW  are
       specified in POSIX.1-2001.

       Значения  F_GETOWN  и  F_SETOWN  определены  в  POSIX.1-2001.  Для  получения  их определений, определите
       _XOPEN_SOURCE со значением 500 или больше или _POSIX_C_SOURCE со значением 200809L или больше.

       F_DUPFD_CLOEXEC  указана  в  POSIX.1-2008.  Для  получения  определения,  определите  _POSIX_C_SOURCE  со
       значением 200809L или больше, или _XOPEN_SOURCE со значением 700 или больше.

ПРИМЕЧАНИЯ

       Ошибки, возвращаемые dup2(2), отличаются от тех, что возвращаются при F_DUPFD.

   Файловая блокировка
       The  original  Linux  fcntl()   system  call  was not designed to handle large file offsets (in the flock
       structure).  Consequently, an fcntl64() system call was added  in  Linux  2.4.   The  newer  system  call
       employs  a  different  structure  for  file  locking,  flock64,  and corresponding operations, F_GETLK64,
       F_SETLK64, and F_SETLKW64.  However, these details can be ignored  by  applications  using  glibc,  whose
       fcntl() wrapper function transparently employs the more recent system call where it is available.

   Обычные блокировки (Record locks)
       Since Linux 2.0, there is no interaction between the types of lock placed by flock(2)  and fcntl().

       Некоторые  системы имеют дополнительные поля в структуре struct flock, например, l_sysid (признак машины,
       на которой  удерживается  блокировка).  Вообще  говоря,  один  l_pid  не  очень  полезен,  если  процесс,
       удерживающий  блокировку,  может  работать  на  другой машине; в Linux, хотя это поле и есть на некоторых
       архитектурах (например, MIPS32), но оно не используется.

       The original Linux fcntl()  system call was not designed to handle  large  file  offsets  (in  the  flock
       structure).   Consequently,  an  fcntl64()  system  call  was  added in Linux 2.4.  The newer system call
       employs a different structure  for  file  locking,  flock64,  and  corresponding  operations,  F_GETLK64,
       F_SETLK64,  and  F_SETLKW64.   However,  these  details can be ignored by applications using glibc, whose
       fcntl() wrapper function transparently employs the more recent system call where it is available.

   Блокировка и NFS
       До Linux 3.12, если клиент NFSv4 теряет связь с сервером на некоторый период времени (более  90  секунд),
       то  он  может  потерять  и  перезапросить блокировки даже не зная об этом (период времени, после которого
       контакт предполагается потерянным в NFSv4 называется время аренды (leasetime). У Linux в сервере NFS  его
       можно узнать по значению в /proc/fs/nfsd/nfsv4leasetime, которое отражает период в секундах. В этом файле
       значение  по  умолчанию равно 90). Данный сценарий несёт потенциальный риск повреждения данных, так как в
       этот перерыв другой процесс может установить блокировку и выполнить файловый ввод-вывод.

       Начиная с Linux 3.12, если клиент  NFSv4  теряет  контакт  с  сервером,  то  любой  файловый  ввод-вывод,
       выполняемый  процессом,  который  «думает», что имеет блокировку, будет завершаться с ошибкой до тех пор,
       пока этот процесс не закроет и не переоткроет файл. Чтобы  вернуть  поведение,  которое  было  до  версии
       pre-3.12,  можно  параметру  ядра  nfs.recover_lost_locks  присвоить  значение  1, из-за чего клиент буде
       пытаться восстановить  потерянные  блокировки  при  переустановлении  связи  с  сервером.  Из-за  наличия
       сопутствующего риска повреждения данных, значение данного параметра по умолчанию равно 0 (отключено).

ОШИБКИ

   F_SETFL
       Невозможно  использовать  F_SETFL для смены состояния флагов O_DSYNC и O_SYNC. Попытка изменить состояние
       этих флагов просто игнорируется.

   F_GETOWN
       A limitation of the Linux system call conventions on some architectures (notably i386) means  that  if  a
       (negative)   process  group ID to be returned by F_GETOWN falls in the range -1 to -4095, then the return
       value is wrongly interpreted by glibc as an error in the system  call;  that  is,  the  return  value  of
       fcntl()   will  be  -1,  and  errno  will  contain  the  (positive) process group ID.  The Linux-specific
       F_GETOWN_EX operation avoids this problem.  Since glibc 2.11, glibc makes  the  kernel  F_GETOWN  problem
       invisible by implementing F_GETOWN using F_GETOWN_EX.

   F_SETOWN
       В  Linux  2.4  и  более  раннем,  есть  ошибка, которая может произойти когда непривилегированный процесс
       использует F_SETOWN для задания владельца дескриптора файла сокета как  процесса  (группу)  отличного  от
       вызывающего.  В  этом  случае  fcntl() может вернуть -1 с errno равным EPERM, даже когда процесс (группа)
       владелец такая же как и вызывающий имеет право посылать сигнал. Несмотря на возвращаемую ошибку, владелец
       файлового дескриптора всё равно устанавливается и сигналы будут посылаться владельцу.

   Обнаружение взаимных блокировок (deadlock)
       Алгоритм обнаружения взаимных блокировок задействуется ядром при работе  с  запросами  F_SETLKW  и  может
       закончиться  как ненахождением (не удалось обнаружить взаимную блокировку и процессы блокируют друг друга
       навсегда), так и ошибочным нахождением (ошибка EDEADLK, но взаимная  блокировка  отсутствует).  Например,
       ограничение  ядра  на  вложенность зависимостей блокировки при поиске равна 10, что означает, что цепочки
       циклических зависимостей, превышающие этот  размер,  не  будут  обнаружены.  Также  ядро  может  ошибочно
       посчитать  за  взаимную  блокировку  ситуацию, когда два и более процесса, созданных с помощью clone(2) с
       флагом CLONE_FILES, размещают блокировки, которые похожи (для ядра) на конфликтующие.

   Обязательная (mandatory) блокировка
       Реализация обязательной  блокировки  в  Linux  проводит  к  состязательности  процессов,  что  делает  её
       ненадёжной:  вызов  write(2),  пересекающийся  с  блокировкой,  может  изменить данные после установления
       обязательной блокировки; вызов read(2),  пересекающийся  с  блокировкой,  может  обнаружить  изменившиеся
       данные,  которые были внесены уже установления блокировки на запись. Подобная состязательность существует
       между  обязательными  блокировками  и  mmap(2).  Поэтому  нецелесообразно  полагаться   на   обязательную
       блокировку.

СМОТРИТЕ ТАКЖЕ

       dup2(2), flock(2), open(2), socket(2), lockf(3), capabilities(7), feature_test_macros(7), lslocks(8)

       Файлы  locks.txt,  mandatory-locking.txt  и  dnotify.txt из каталога Documentation/filesystems. исходного
       кода ядра Linux (в старых ядрах  эти  файлы  были  в  каталоге  Documentation/,  а  mandatory-locking.txt
       назывался mandatory.txt).

ПЕРЕВОД

       Русский  перевод  этой  страницы  руководства  разработал(и) Azamat Hackimov <azamat.hackimov@gmail.com>,
       Dmitry   Bolkhovskikh   <d20052005@yandex.ru>,   Yuri   Kozlov    <yuray@komyakino.ru>,    Иван    Павлов
       <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>

       Этот  перевод является свободной программной документацией; он распространяется на условиях общедоступной
       лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html  версии  3  или
       более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

       Если  вы  обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом
       разработчику(ам)  по  его(их)  адресу(ам)  электронной  почты  или  по   адресу   списка рассылки русских
       переводчиков.

Справочные страницы Linux 6.9.1                   2 мая 2024 г.                                         fcntl(2)