.\" -*- coding: UTF-8 -*- .\" This manpage is Copyright (C) 1992 Drew Eckhardt; .\" and Copyright (C) 1993 Michael Haardt, Ian Jackson; .\" and Copyright (C) 1998 Jamie Lokier; .\" and Copyright (C) 2002-2010, 2014 Michael Kerrisk; .\" and Copyright (C) 2014 Jeff Layton .\" and Copyright (C) 2014 David Herrmann .\" and Copyright (C) 2017 Jens Axboe .\" .\" %%%LICENSE_START(VERBATIM) .\" Permission is granted to make and distribute verbatim copies of this .\" manual provided the copyright notice and this permission notice are .\" preserved on all copies. .\" .\" Permission is granted to copy and distribute modified versions of this .\" manual under the conditions for verbatim copying, provided that the .\" entire resulting derived work is distributed under the terms of a .\" permission notice identical to this one. .\" .\" Since the Linux kernel and libraries are constantly changing, this .\" manual page may be incorrect or out-of-date. The author(s) assume no .\" responsibility for errors or omissions, or for damages resulting from .\" the use of the information contained herein. The author(s) may not .\" have taken the same level of care in the production of this manual, .\" which is licensed free of charge, as they might when working .\" professionally. .\" .\" Formatted or processed versions of this manual, if unaccompanied by .\" the source, must acknowledge the copyright and authors of this work. .\" %%%LICENSE_END .\" .\" Modified 1993-07-24 by Rik Faith .\" Modified 1995-09-26 by Andries Brouwer .\" and again on 960413 and 980804 and 981223. .\" Modified 1998-12-11 by Jamie Lokier .\" Applied correction by Christian Ehrhardt - aeb, 990712 .\" Modified 2002-04-23 by Michael Kerrisk .\" Added note on F_SETFL and O_DIRECT .\" Complete rewrite + expansion of material on file locking .\" Incorporated description of F_NOTIFY, drawing on .\" Stephen Rothwell's notes in Documentation/dnotify.txt. .\" Added description of F_SETLEASE and F_GETLEASE .\" Corrected and polished, aeb, 020527. .\" Modified 2004-03-03 by Michael Kerrisk .\" Modified description of file leases: fixed some errors of detail .\" Replaced the term "lease contestant" by "lease breaker" .\" Modified, 27 May 2004, Michael Kerrisk .\" Added notes on capability requirements .\" Modified 2004-12-08, added O_NOATIME after note from Martin Pool .\" 2004-12-10, mtk, noted F_GETOWN bug after suggestion from aeb. .\" 2005-04-08 Jamie Lokier , mtk .\" Described behavior of F_SETOWN/F_SETSIG in .\" multithreaded processes, and generally cleaned .\" up the discussion of F_SETOWN. .\" 2005-05-20, Johannes Nicolai , .\" mtk: Noted F_SETOWN bug for socket file descriptor in Linux 2.4 .\" and earlier. Added text on permissions required to send signal. .\" 2009-09-30, Michael Kerrisk .\" Note obsolete F_SETOWN behavior with threads. .\" Document F_SETOWN_EX and F_GETOWN_EX .\" 2010-06-17, Michael Kerrisk .\" Document F_SETPIPE_SZ and F_GETPIPE_SZ. .\" 2014-07-08, David Herrmann .\" Document F_ADD_SEALS and F_GET_SEALS .\" 2017-06-26, Jens Axboe .\" Document F_{GET,SET}_RW_HINT and F_{GET,SET}_FILE_RW_HINT .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH FCNTL 2 "21 декабря 2020 г." Linux "Руководство программиста Linux" .SH ИМЯ fcntl \- работа с файловым дескриптором .SH СИНТАКСИС .nf \fB#include \fP \fB#include \fP .PP \fBint fcntl(int \fP\fIfd\fP\fB, int \fP\fIcmd\fP\fB, ... /* \fP\fIarg\fP\fB */ );\fP .fi .SH ОПИСАНИЕ \fBfcntl\fP() позволяет выполнять различные команды над открытым файловым дескриптором \fIfd\fP. Команда определяется содержимым аргумента \fIcmd\fP. .PP \fBfcntl\fP() может принимать необязательный третий аргумент. Необходимость его указания зависит от значения, указанного в \fIcmd\fP. Тип необходимого аргумента указан в скобках после каждого имени значения \fIcmd\fP (в большинстве случаев требуется тип \fIint\fP, и мы определяем аргумент с помощью имени \fIarg\fP), или указывается \fIvoid\fP, если аргумент не нужен. .PP Некоторые операции, описанные далее, поддерживаются только начиная с определённой версии ядра Linux. Корректным методом проверки доступности операции в ядре является вызов \fBfcntl\fP() с желаемой операцией в \fIcmd\fP и сравнение кода возврата вызов с \fBEINVAL\fP, который указывает на неподдерживаемость значения ядром. .SS "Создание дубликата файлового дескриптора" .TP \fBF_DUPFD\fP (\fIint\fP) Создаёт копию файлового дескриптора \fIfd\fP, используя и наименьший доступный номер файлового дескриптора, который больше или равен \fIarg\fP. Отличие от \fBdup2\fP(2) в том, что там файловый дескриптор задаётся явно. .IP При успешном выполнении этой команды, возвращается новый файловый дескриптор. .IP Дополнительную информацию смотрите в \fBdup\fP(2). .TP \fBF_DUPFD_CLOEXEC\fP (\fIint\fP; начиная с Linux 2.6.24) Как \fBF_DUPFD\fP, но на новом файловом дескрипторе дополнительно устанавливается флаг закрытия\-при\-выполнении. Установка этого флага позволяет программам не делать дополнительный вызов \fBfcntl\fP() с командой \fBF_SETFD\fP для установки флага \fBFD_CLOEXEC\fP. О том, зачем нужен этот флаг, смотрите описание \fBO_CLOEXEC\fP в \fBopen\fP(2). .SS "Флаги файлового дескриптора" Следующие команды работают с флагами, связанными с файловым дескриптором. В настоящее время определён только один флаг: \fBFD_CLOEXEC\fP, флаг close\-on\-exec. Если бит \fBFD_CLOEXEC\fP равен 1, то файловый дескриптор будет автоматически закрыт при успешном вызове \fBexecve\fP(2) (если \fBexecve\fP(2) завершится с ошибкой, то файловый дескриптор останется открытым). Если бит \fBFD_CLOEXEC\fP равен 0, то файловый дескриптор останется открытым после \fBexecve\fP(2). .TP \fBF_GETFD\fP (\fIvoid\fP) Вернуть (как результат функции) флаги файлового дескриптора; значение \fIarg\fP игнорируется. .TP \fBF_SETFD\fP (\fIint\fP) Установить флаги файлового дескриптора согласно значению, указанному в аргументе \fIarg\fP. .PP В многонитевых программах использование \fBfcntl\fP() с \fBF_SETFD\fP для установки флага close\-on\-exec в то время как другая нить выполняет \fBfork\fP(2) плюс \fBexecve\fP(2) приводит к состязательности, что может вызвать передачу файлового дескриптора программе, запущенной в дочернем процессе. Смотрите обсуждение флага \fBO_CLOEXEC\fP в \fBopen\fP(2) и решение проблемы. .SS "Флаги состояния файла" .\" or .\" .BR creat (2), Каждое описание открытого файла имеет несколько связанных с ним флагов состояния, которые инициализируются вызовом \fBopen\fP(2) и, возможно, изменяются затем вызовом \fBfcntl\fP(). Эти флаги совместно используются копиями файловых дескрипторов (сделанными с помощью \fBdup\fP(2), \fBfcntl\fP(F_DUPFD), \fBfork\fP(2) и т.д.), которые указывают на одно описание открытого файла. .PP Эти флаги состояния и их смысл описаны в \fBopen\fP(2). .TP \fBF_GETFL\fP (\fIvoid\fP) Вернуть (как результат функции) режим доступа к файлу и флаги состояния файла; значение \fIarg\fP игнорируется. .TP \fBF_SETFL\fP (\fIint\fP) Установить флаги состояния файла согласно значению, указанному в аргументе \fIarg\fP. Режим доступа к файлу (\fBO_RDONLY\fP, \fBO_WRONLY\fP, \fBO_RDWR\fP) и флаги создания файла (т. е., \fBO_CREAT\fP, \fBO_EXCL\fP, \fBO_NOCTTY\fP, \fBO_TRUNC\fP) в \fIarg\fP игнорируются. В Linux эта команда может изменять только флаги \fBO_APPEND\fP, \fBO_ASYNC\fP, \fBO_DIRECT\fP, \fBO_NOATIME\fP и \fBO_NONBLOCK\fP. Невозможно изменить флаги \fBO_DSYNC\fP и \fBO_SYNC\fP; смотрите ДЕФЕКТЫ далее. .SS "Консультативная (advisory) блокировка" В Linux реализована обычная («попроцессная») блокировка UNIX, стандартизованная POSIX. Описание Linux\-альтернативную блокировку открытых файловых описаний с лучшей семантикой смотрите далее. .PP Команды \fBF_SETLK\fP, \fBF_SETLKW\fP и \fBF_GETLK\fP используются для установки, снятия и тестирования существования блокировок записей (также известных как блокировки байтового диапазона, сегмента или области файла). Третий аргумент, \fIlock\fP, является указателем на структуру, которая имеет, по крайней мере, следующие поля (в произвольном порядке): .PP .in +4n .EX 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) */ ... }; .EE .in .PP Поля \fIl_whence\fP, \fIl_start\fP и \fIl_len\fP этой структуры задают диапазон байт, который мы хотим заблокировать. Могут блокироваться байты за концом файла, но не перед началом файла. .PP \fIl_start\fP \(em это начальное смещение для блокировки, которое интерпретируется как начало файла (если значение \fIl_whence\fP равно \fBSEEK_SET\fP); как текущая позиция в файле (если значение \fIl_whence\fP равно \fBSEEK_CUR\fP); как конец файла (если значение \fIl_whence\fP равно \fBSEEK_END\fP). В последних двух случаях, \fIl_start\fP может иметь отрицательное значение, предоставляя смещение, которого не может указать до начала файла. .PP В \fIl_len\fP задаётся количество байт, которые нужно заблокировать. Если \fIl_len\fP положительно, то диапазон блокировки начинается со \fIl_start\fP и кончается \fIl_start\fP+\fIl_len\fP\-1 включительно. Если в \fIl_len\fP указан 0, то блокируются все байты начиная с места, указанного \fIl_whence\fP и \fIl_start\fP и до конца файла, независимо от величины файла. .PP POSIX.1\-2001 позволяет (но не требует) реализации поддерживать отрицательное значение \fIl_len\fP; если \fIl_len\fP отрицательно, то интервал, описываемый \fIlock\fP, имеет размер \fIl_start\fP+\fIl_len\fP до \fIl_start\fP\-1 включительно. Это поддерживается в Linux начиная с ядер версии 2.4.21 и 2.5.49. .PP Поле \fIl_type\fP может быть использовано для указания типа блокировки файла: чтение (\fBF_RDLCK\fP) или запись (\fBF_WRLCK\fP). Любое количество процессов могут удерживать блокировку на чтение (общая блокировка) области файла, но только один процесс может удерживать блокировку на запись (эксклюзивная блокировка). Эксклюзивная блокировка исключает все другие блокировки, как общие так и эксклюзивные. Один процесс может удерживать только один тип блокировки области файла; если происходит новая блокировка уже заблокированной области, то существующая блокировка преобразуется в новый тип блокировки. (Такие преобразования могут привести к разбиению, уменьшению или срастанию с существующей блокировкой, если диапазон байт, заданный для новой блокировки, неточно совпадает с диапазоном существующей блокировки.) .TP \fBF_SETLK\fP (\fIstruct flock *\fP) Установить блокировку (когда \fIl_type\fP равен \fBF_RDLCK\fP или \fBF_WRLCK\fP) или снять блокировку (когда \fIl_type\fP равен \fBF_UNLCK\fP) байтов, указанных полями \fIl_whence\fP, \fIl_start\fP и \fIl_len\fP структуры \fIlock\fP. Если конфликтующая блокировка удерживается другим процессом, то данный вызов вернёт \-1 и установит значение \fIerrno\fP в \fBEACCES\fP или \fBEAGAIN\fP (ошибка, возвращаемая в этом случае, в разных реализациях разная, поэтому в POSIX для переносимых приложений требуется проверять оба значения). .TP \fBF_SETLKW\fP (\fIstruct flock *\fP) Как \fBF_SETLK\fP, но если конфликтующая блокировка удерживается на файле, то выполняется ожидание снятия этой блокировки. Если во время ожидания поступил сигнал, то данный вызов прерывается и (после возврата из обработчика сигнала) из него происходит немедленный возврат (возвращается значение \-1 и \fIerrno\fP устанавливается в \fBEINTR\fP; см. \fBsignal\fP(7)). .TP \fBF_GETLK\fP (\fIstruct flock *\fP) При входе в этот вызов, \fIlock\fP описывает блокировку, которую мы хотели бы установить на файл. Если такая блокировка не может быть установлена, \fBfcntl\fP() не устанавливает её, но возвращает \fBF_UNLCK\fP в поле \fIl_type\fP структуры \fIlock\fP и оставляет другие поля структуры неизменёнными. .IP Если одна или более несовместимых блокировок мешают установке этой блокировки, то \fBfcntl\fP() возвращает подробности об одной из этих блокировок в полях \fIl_type\fP, \fIl_whence\fP, \fIl_start\fP и \fIl_len\fP структуры \fIlock\fP. Если конфликтующая блокировка является обычной (попроцессной), то в \fIl_pid\fP записывается значение PID того процесса, который удерживает блокировку. Если конфликтующая блокировка является блокировку открытого файлового описания, в \fIl_pid\fP записывается \-1. Заметим, что возвращаемая информация может уже устареть в момент проверки вызывающим. .PP Для того, чтобы установить блокировку на чтение, \fIfd\fP должен быть открыт на чтение. Для того, чтобы установить блокировку на запись, \fIfd\fP должен быть открыт на запись. Чтобы установить оба типа блокировки, дескриптор должен быть открыт на запись и на чтение. .PP При размещении блокировок с помощью \fBF_SETLKW\fP, ядро обнаруживает \fIвзаимные блокировки\fP (deadlocks), при которых два и более процессов создают запросы на блокировку, блокируемые блокировками, удерживаемые другими процессами. Например, предположим, что процесс А удерживает блокировку на запись файла в байт 100, а процесс Б удерживает блокировку на запись в байт 200. Если каждый процесс затем попытается заблокировать байт, который уже заблокирован другим процессом с помощью \fBF_SETLKW\fP, то без обнаружения взаимных блокировок оба процесса останутся заблокированными навсегда. Когда ядро обнаруживает такие взаимные блокировки оно сразу же завершает одну из блокирующих блокировок с ошибкой \fBEDEADLK\fP; приложение, встретившее такую ошибку, должно освободить одну из своих блокировок перед попыткой восстановить блокировки, которые ему нужны, позволив другому приложению продолжить работу. Зацикленные взаимные блокировки обнаруживаются и для более двух процессов. Однако заметим, что есть ограничения в алгоритме обнаружения взаимных блокировок; смотрите ДЕФЕКТЫ. .PP Также как и при снятии блокировки через явное указание \fBF_UNLCK\fP, блокировка автоматически снимается, когда процесс завершается. .PP Блокировки не наследуются потомком, созданным через \fBfork\fP(2), но сохраняются при вызове \fBexecve\fP(2). .PP Поскольку буферизация выполняется через библиотеку \fBstdio\fP(3), использование блокировок с функциями в этом пакете нужно избегать; вместо этих функций используйте \fBread\fP(2) и \fBwrite\fP(2). .PP Записи о блокировках, описанных выше, связаны с процессом (в отличие от блокировках открытых файловых описаний, описанных далее). Это приводит к некоторым печальным последствиям: .IP * 3 .\" (Additional file descriptors referring to the same file .\" may have been obtained by calls to .\" .BR open "(2), " dup "(2), " dup2 "(2), or " fcntl ().) Если процесс закрывает \fIлюбой\fP файловый дескриптор, ссылающийся на файл, то освобождаются все блокировки процесса для этого файла, независимо от файлового дескриптора(ов), на который получена блокировка. Это плохо: это означает, что процесс может потерять свои блокировки на файл, такой как \fI/etc/passwd\fP или \fI/etc/mtab\fP, когда какой\-либо причине библиотечная функция решает их открыть, прочитать и закрыть. .IP * Нити процесса совместно используют блокировки процесса. Другими словами многонитевая программа не может использовать блокировку для разграничения доступа к одной области файла среди нитей. .PP Блокировки открытых файловых описаний решают обе эти проблемы. .SS "Блокировки открытых файловых описаний (не POSIX)" .\" FIXME . Review progress into POSIX .\" http://austingroupbugs.net/view.php?id=768 Блокировки открытых файловых описаний являются консультативными блокировками диапазона байт, чьё действие почти идентично обычным блокировкам, описанным выше. Данный тип блокировок есть только в Linux и доступен с версии 3.15 (есть предложение в Austin Group включить данный тип блокировки в следующую версию POSIX.1). Описание открытых файловых описаний смотрите в \fBopen\fP(2). .PP Принципиальное различие между двумя типами блокировок в том, что обычные блокировки связаны с процессом, а блокировки открытых файловых описаний связаны с открытым файловым описанием, для которого они получены (очень похоже на блокировки, получаемые с помощью \fBflock\fP(2). В следствие этого (и в отличие от обычных консультативных блокировок), блокировки открытых файловых описаний наследуются при \fBfork\fP(2) (и при \fBclone\fP(2) с \fBCLONE_FILES\fP), и освобождаются только автоматически при последнем закрытии открытого файлового описания, а не при любом закрытии файла. .PP Конфликт комбинаций блокировок (блокировка чтения и блокировка записи или две блокировки записи), при котором одна блокировка — открытое файловое описание, а другая — обычная блокировка, конфликтуют даже когда они запрашиваются одним процессом для одного и того же файлового дескриптора. .PP Блокировки открытых файловых описаний, полученные для одного и того же файлового описания (т. е., для одного и того же файлового дескриптора или его копии, созданной в результате \fBfork\fP(2), \fBdup\fP(2), \fBfcntl\fP() \fBF_DUPFD\fP и т. п.), всегда совместимы: если новая блокировка помещается на уже заблокированную область, то существующая блокировка преобразуется в блокировку нового типа (такие преобразования могут приводить к разделению, сокращению или объединению существующей блокировки, как описывалось ранее). .PP С другой стороны, блокировки открытых файловых описаний могут конфликтовать друг с другом, когда они запрашиваются через разные открытые файловые описания. То есть, нити в многонитевых программах могут использовать блокировки открытых файловых описаний для синхронизации доступа к области файла, если каждая нить выполняет отдельный вызов \fBopen\fP(2) на файл и применяет блокировки для получаемого файлового дескриптора. .PP Как и у обычных блокировок, третий аргумент \fBfcntl\fP(), \fIlock\fP, является указателем на структуру \fIflock\fP. Но в отличие от обычных блокировок при использовании команд, описанных далее, поле \fIl_pid\fP этой структуры должно иметь значение 0. .PP Команды для работы с блокировками открытых файловых описаний аналогичны используемым для обычных блокировок: .TP \fBF_OFD_SETLK\fP (\fIstruct flock *\fP) Установить блокировку открытого файлового описания (когда \fIl_type\fP равен \fBF_RDLCK\fP или \fBF_WRLCK\fP) или снять блокировку открытого файлового описания (когда \fIl_type\fP равен \fBF_UNLCK\fP) байтов, указанных полями \fIl_whence\fP, \fIl_start\fP и \fIl_len\fP структуры \fIlock\fP. Если конфликтующая блокировка удерживается другим процессом, то данный вызов вернёт \-1 и установит значение \fIerrno\fP в \fBEAGAIN\fP. .TP \fBF_OFD_SETLKW\fP (\fIstruct flock *\fP) Как \fBF_OFD_SETLK\fP, но если конфликтующая блокировка удерживается на файле, то выполняется ожидание снятия этой блокировки. Если во время ожидания поступил сигнал, то данный вызов прерывается и (после возврата из обработчика сигнала) из него происходит немедленный возврат (возвращается значение \-1 и \fIerrno\fP устанавливается в \fBEINTR\fP; см. \fBsignal\fP(7)). .TP \fBF_OFD_GETLK\fP (\fIstruct flock *\fP) В начала данного вызова значение \fIlock\fP описывает блокировку открытого файлового описания, которую мы бы хотели создать на файле. Если блокировка возможна, то в действительности \fBfcntl\fP() её не создаёт, а возвращает \fBF_UNLCK\fP в поле \fIl_type\fP у \fIlock\fP, оставляя остальные поля неизменными. Если есть одна или более несовместимых блокировок, препятствующих получению, то в \fIlock\fP возвращается подробная информация об этих блокировках, как описывалось выше для \fBF_GETLK\fP. .PP .\" commit 57b65325fe34ec4c917bc4e555144b4a94d9e1f7 .\" В текущей реализации для блокировок открытых файловых описаний обнаружение взаимных блокировок не выполняется (в этом отличие от попроцессных блокировок, для которых ядро выполняет обнаружение взаимных блокировок). .SS "Обязательная (mandatory) блокировка" \fIПредупреждение\fP: реализация Linux обязательного блокирования ненадёжна. Смотрите раздел ДЕФЕКТЫ далее. Из\-за этих дефектов и того факта, что это свойство, вероятно, мало где будет использоваться, начиная с Linux 4.5 обязательная блокировка был сделана необязательной, и включается параметром настройки (\fBCONFIG_MANDATORY_FILE_LOCKING\fP). Это первый шаг последующего полного удаления данного свойства. .PP По умолчанию, обычные (связанные с процессом) блокировки и блокировки открытого файлового описания являются консультативными. Консультативные блокировки не обязательны к выполнению и полезны только в сотрудничающих процессах. .PP Оба типа блокировки могут быть также обязательными. Если процесс пытается получить несовместимый доступ (например, \fBread\fP(2) и \fBwrite\fP(2)) к области файла, на которую установлена несовместимая обязательная блокировка, то результат зависит от состояния флага \fBO_NONBLOCK\fP в описании этого открытого файла. Если флаг \fBO_NONBLOCK\fP не установлен, то системный вызов блокируется до удаления блокировки или преобразуется в режим, который совместим с доступом. Если флаг \fBO_NONBLOCK\fP установлен, то системный вызов завершается с ошибкой \fBEAGAIN\fP. .PP Чтобы использовать обязательные блокировки, обязательное блокирование должно быть включено в файловой системе, содержащей файл, и на самом файле. Обязательное блокирование включается в файловой системе с помощью параметра «\-o mand» команды \fBmount\fP(8) или с помощью флага \fBMS_MANDLOCK\fP в \fBmount\fP(2). Обязательное блокирование включается на файле посредством отключения права исполнения группе и установкой бита set\-group\-ID (см. \fBchmod\fP(1) и \fBchmod\fP(2)). .PP .\" Обязательная блокировка не описана в POSIX. В некоторых других системах обязательная блокировка также поддерживается, хотя процесс её создания различен. .SS "Потерянные блокировки" При получении консультативной блокировки на сетевой файловой системе, например NFS, возможна её потеря. Это может случиться из\-за административного действия или сетевой проблемы (т. е., потеря связи с сервером), которая длится достаточно долго для того, чтобы сервер посчитал клиента за неработающего. .PP .\" commit ef1820f9be27b6ad158f433ab38002ab8131db4d Когда файловая система определяет, что блокировка потеряна, последующие запросы \fBread\fP(2) или \fBwrite\fP(2) могут завершиться ошибкой \fBEIO\fP. Эта ошибка будет повторяться до тех пор, пока блокировка не удалится или не закроется файловый дескриптор. Начиная с Linux 3.12, так работает, по крайней мере, NFSv4 (включая все предыдущие версии). .PP .\" Некоторые версии UNIX при таких обстоятельствах посылают сигнал (\fBSIGLOST\fP). В Linux такой сигнал не определён и не существует какого\-либо асинхронного уведомления о потере блокировки. .SS "Управление сигналами" Для управления сигналами доступности ввода/вывода используются команды \fBF_GETOWN\fP, \fBF_SETOWN\fP, \fBF_GETOWN_EX\fP, \fBF_SETOWN_EX\fP, \fBF_GETSIG\fP и \fBF_SETSIG\fP: .TP \fBF_GETOWN\fP (\fIvoid\fP) Return (as the function result) the process ID or process group ID currently receiving \fBSIGIO\fP and \fBSIGURG\fP signals for events on file descriptor \fIfd\fP. Process IDs are returned as positive values; process group IDs are returned as negative values (but see BUGS below). \fIarg\fP is ignored. .TP \fBF_SETOWN\fP (\fIint\fP) Установить идентификатор процесса или группы процесса, которые будут принимать сигналы \fBSIGIO\fP и \fBSIGURG\fP для событий на файловом дескрипторе \fIfd\fP. Идентификатор целевого процесса или группы процессов задаётся в аргументе \fIarg\fP. Идентификатор процесса задаётся положительным числом, идентификатор группы задаётся отрицательным числом. Обычно, вызывающий процесс указывает самого себя в качестве владельца (то есть в \fIarg\fP указывается результат \fBgetpid\fP(2)). .IP Помимо установки владельца дескриптора файла, также нужно включить генерацию сигналов для файлового дескриптора. Это делается посредством установки флага состояния \fBO_ASYNC\fP в файловом дескрипторе с помощью \fBfcntl\fP() с командой \fBF_SETFL\fP. После этого сигнал \fBSIGIO\fP посылается всякий раз, когда для данного файлового дескриптора становится возможным ввод или вывод. Для включения доставки сигнала, отличного от \fBSIGIO\fP, можно использовать команду \fBF_SETSIG\fP вызова \fBfcntl\fP(). .IP Отправка сигнала процессу\-владельцу (группе), указанному с помощью \fBF_SETOWN\fP — такая же проверка прав, как описано в \fBkill\fP(2), где посылающий процесс один из тех, который может пользоваться \fBF_SETOWN\fP (но смотрите раздел ДЕФЕКТЫ далее). Если проверка не проходит, то сигнал просто отбрасывается. \fIЗамечание\fP: операция \fBF_SETOWN\fP сохраняет мандаты вызывающего на момент вызова \fBfcntl\fP(), и эти сохранённые мандаты затем используются при проверке прав. .IP .\" The following appears to be rubbish. It doesn't seem to .\" be true according to the kernel source, and I can write .\" a program that gets a terminal-generated SIGIO even though .\" it is not the foreground process group of the terminal. .\" -- MTK, 8 Apr 05 .\" .\" If the file descriptor .\" .I fd .\" refers to a terminal device, then SIGIO .\" signals are sent to the foreground process group of the terminal. Если файловый дескриптор \fIfd\fP указывает на сокет, то по команде \fBF_SETOWN\fP для него также выбирается получатель сигналов \fBSIGURG\fP, которые доставляются, когда на сокет поступают внеполосные данные. (\fBSIGURG\fP посылается во всех ситуациях, когда вызов \fBselect\fP(2) говорит, что сокет находится в состоянии "исключительной ситуации".) .IP Следующее верно для ядер 2.6.x, до 2.6.11 включительно: .RS .IP .\" The relevant place in the (2.6) kernel source is the .\" 'switch' in fs/fcntl.c::send_sigio_to_task() -- MTK, Apr 2005 .\" send_sigurg()/send_sigurg_to_task() bypasses .\" kill_fasync()/send_sigio()/send_sigio_to_task() .\" to directly call send_group_sig_info() .\" -- MTK, Apr 2005 (kernel 2.6.11) Если для \fBF_SETSIG\fP передаётся ненулевое значение в многонитевой процесс, работающий с библиотекой нитей (например, NPTL), которая обеспечивает поддержку групп нитей, то положительное значение, переданное \fBF_SETOWN\fP, имеет другой смысл: вместо указания ID процесса, описывающего весь процесс, она является ID нити, указывающим на определённую нить процесса. Поэтому может понадобиться передать в \fBF_SETOWN\fP результат \fBgettid\fP(2), а не \fBgetpid\fP(2), чтобы получить правильный результат при использовании \fBF_SETSIG\fP. (В имеющихся реализациях Linux ID главной нити совпадает с ID процесса. Это означает, что в программе с одной нитью можно использовать любой вызов, \fBgettid\fP(2) или \fBgetpid\fP(2), в этом случае.) Однако заметим, что утверждения этого абзаца не применимы к сигналу \fBSIGURG\fP, генерируемому для внеполосных данных сокета: этот сигнал всегда посылается или процессу или группе процессов, в зависимости от значения, указанного для \fBF_SETOWN\fP. .RE .IP Описанное выше поведение было случайно удалено из Linux 2.6.12, и так и не восстановлено. Начиная с Linux 2.6.32 используйте \fBF_SETOWN_EX\fP при назначении сигналов \fBSIGIO\fP и \fBSIGURG\fP для определённой нити. .TP \fBF_GETOWN_EX\fP (\fIstruct f_owner_ex *\fP) (начиная с Linux 2.6.32) Получить настройки владения текущим файловым дескриптором, установленные предыдущей командой \fBF_SETOWN_EX\fP. Информация возвращается в структуре, указанной в \fIarg\fP, которая имеет следующий вид: .IP .in +4n .EX struct f_owner_ex { int type; pid_t pid; }; .EE .in .IP Поле \fItype\fP будет равно: \fBF_OWNER_TID\fP, \fBF_OWNER_PID\fP или \fBF_OWNER_PGRP\fP. Значением поля \fIpid\fP будет положительное целое, представляющее ID нити, ID процесса или ID группы процессов. Подробности смотрите в описании \fBF_SETOWN_EX\fP. .TP \fBF_SETOWN_EX\fP (\fIstruct f_owner_ex *\fP) (начиная с Linux 2.6.32) Эта команда выполняет задачу, подобную \fBF_SETOWN\fP. Она позволяет вызывающему назначить сигналы доступности ввода\-вывода определённой нити, процессу или группе процессов. Вызывающий указывает приёмник сигналов в \fIarg\fP, выражаемый указателем на структуру \fIf_owner_ex\fP. Поле \fItype\fP имеет одно из следующих значений, которое определяет чем считать \fIpid\fP: .RS .TP \fBF_OWNER_TID\fP Посылать сигнал нити, чей ID (значение, возвращаемое вызовом \fBclone\fP(2) или \fBgettid\fP(2)) указан в \fIpid\fP. .TP \fBF_OWNER_PID\fP Посылать сигнал процессу, чей ID указан в \fIpid\fP. .TP \fBF_OWNER_PGRP\fP Посылать сигнал группе процессов, чей ID указан в \fIpid\fP. (Заметим, что в отличие от \fBF_SETOWN\fP, ID группы процессов здесь задаётся как положительное значение.) .RE .TP \fBF_GETSIG\fP (\fIvoid\fP) Получить (как результат функции) сигнал, посылаемый, когда становится возможным ввод или вывод. Значение 0 означает сигнал \fBSIGIO\fP. Любое другое значение (включая \fBSIGIO\fP) является другим сигналом, и в этом случае для обработчика сигнала доступна дополнительная информация, если он был установлен с \fBSA_SIGINFO\fP. Аргумент \fIarg\fP игнорируется. .TP \fBF_SETSIG\fP (\fIint\fP) .\" .\" The following was true only up until 2.6.11: .\" .\" Additionally, passing a nonzero value to .\" .B F_SETSIG .\" changes the signal recipient from a whole process to a specific thread .\" within a process. .\" See the description of .\" .B F_SETOWN .\" for more details. Установить сигнал, который будет посылаться когда станет возможен ввод или вывод, в значение, указанное в \fIarg\fP. Значение 0 означает сигнал по умолчанию \fBSIGIO\fP. Любое другое значение (включая \fBSIGIO\fP) является другим сигналом, и в этом случае, для обработчика сигнала доступна дополнительная информация, если он был установлен с \fBSA_SIGINFO\fP. .IP В случае использования \fBF_SETSIG\fP с ненулевым значением и установкой \fBSA_SIGINFO\fP для обработчика сигнала (см. \fBsigaction\fP(2)) обработчику передаётся дополнительная информация о событиях ввода/вывода в структуре \fIsiginfo_t\fP. Если поле \fIsi_code\fP показывает, что источник \(em \fBSI_SIGIO\fP, то поле \fIsi_fd\fP содержит файловый дескриптор, ассоциированный с событием. В противном случае не существует никакого механизма, чтобы сообщить с каким файловым дескриптором связан полученный сигнал, и вы должны использовать обычные механизмы (\fBselect\fP(2), \fBpoll\fP(2), \fBread\fP(2) с установленным \fBO_NONBLOCK\fP и т.д.), чтобы определить какой файловый дескриптор доступен для ввода/вывода. .IP Заметим, что файловый дескриптор, предоставляемый в \fIsi_fd\fP, тот же, что указывался при операции \fBF_SETSIG\fP. Это может привести к редкой тупиковой ситуации. Если с файлового дескриптора делался дубль (\fBdup\fP(2) или подобным вызовом), и оригинальный файловый дескриптор закрыт, то события ввода\-вывода будут продолжать генерироваться, но поле \fIsi_fd\fP будет содержать номер теперь уже закрытого файлового дескриптора. .IP При выборе сигнала реального времени (значение >= \fBSIGRTMIN\fP) в очередь может добавляться несколько событий ввода\-вывода с одинаковыми номерами сигналов (размер очереди зависит от доступной памяти). Дополнительная информация будет доступна как описано выше, если для обработчика сигнала будет установлено \fBSA_SIGINFO\fP. .IP .\" See fs/fcntl.c::send_sigio_to_task() (2.4/2.6) sources -- MTK, Apr 05 Заметим, что в Linux есть предел на количество сигналов реального времени, которые могут находиться в очереди процесса (см. \fBgetrlimit\fP(2) и \fBsignal\fP(7)), и если этот предел достигнут, то ядро изменяет пункт доставки \fBSIGIO\fP, и этот сигнал доставляется всему процессу, а не указанной нити. .PP Используя эти механизмы, программа может реализовать полностью асинхронный ввод\-вывод почти не используя в своей работе \fBselect\fP(2) или \fBpoll\fP(2). .PP Использование \fBO_ASYNC\fP, является специфичным для BSD и Linux. В POSIX.1 описано только использование \fBF_GETOWN\fP и \fBF_SETOWN\fP вместе с сигналом \fBSIGURG\fP для сокетов (в POSIX не определён сигнал \fBSIGIO\fP). \fBF_GETOWN_EX\fP, \fBF_SETOWN_EX\fP, \fBF_GETSIG\fP, and \fBF_SETSIG\fP есть только в Linux. В POSIX описан асинхронный ввод\-вывод и структура \fIaio_sigevent\fP, используемая для сходных действий; они также доступны в Linux как часть библиотеки GNU C (Glibc). .SS Аренда Команды \fBF_SETLEASE\fP и \fBF_GETLEASE\fP (в Linux 2.4 и выше) используются для установки новой и получения текущей аренды открытого описания файла, на который указывает файловый дескриптор \fIfd\fP. Аренда файла предоставляет механизм, посредством которого процесс, который удерживает аренду («арендатор»), уведомляется (отправкой сигнала), когда процесс («нарушитель аренды») пытается выполнить вызов \fBopen\fP(2) или \fBtruncate\fP(2) на файл, указанный в этом файловом дескрипторе. .TP \fBF_SETLEASE\fP (\fIint\fP) Установить или удалить аренду файла, в соответствии со значениями, указываемыми в \fIarg\fP: .RS .TP \fBF_RDLCK\fP .\" The following became true in kernel 2.6.10: .\" See the man-pages-2.09 Changelog for further info. Установить аренду чтения. Это приведёт к генерации уведомления вызывающего процесса, когда файл открывается для записи или усечения. Аренда чтения может быть выделена только на файловый дескриптор, открытый только на чтение. .TP \fBF_WRLCK\fP Установить аренду записи. Это приведёт к генерации уведомления вызывающего процесса, когда файл открывается для чтения или записи или выполняется его усечение. Аренда записи может быть установлена на файл, только если этот файл не имеет других открытых файловых дескрипторов. .TP \fBF_UNLCK\fP Удалить аренду с указанного файла. .RE .PP Аренды ассоциируются с открытым файловым описанием (см. \fBopen\fP(2)). Это значит, что дублированные файловые дескрипторы (созданные, например, \fBfork\fP(2) или \fBdup\fP(2)) указывают на одну и ту же аренду, и эта аренда может изменяться или освобождаться через любой из этих дескрипторов. Более того, аренда освобождается или через явную команду \fBF_UNLCK\fP на любом из этих дублированных файловых дескрипторов, или когда все эти файловые дескрипторы будут закрыты. .PP Аренды могут быть выданы только на обычные файлы. Непривилегированный процесс может получить аренду только на файл, чей UID (владельца) совпадает с UID на файловой системе процесса. Процесс с мандатом \fBCAP_LEASE\fP может получить аренду на любые файлы. .TP \fBF_GETLEASE\fP (\fIvoid\fP) Узнать какой тип аренды ассоциирован с файловым дескриптором \fIfd\fP; возвращается одно из значений \fBF_RDLCK\fP, \fBF_WRLCK\fP или \fBF_UNLCK\fP, соответственно означающих аренду на чтение, запись или что аренды нет. Аргумент \fIarg\fP игнорируется. .PP Когда процесс («нарушителя аренды») выполняет вызов \fBopen\fP(2) или \fBtruncate\fP(2), который конфликтует с арендой, установленной через \fBF_SETLEASE\fP, то системный вызов блокируется ядром и ядро уведомляет арендатора сигналом (по умолчанию \fBSIGIO\fP). Арендатор должен при получении этого сигнала выполнить все необходимые действия по очистке для подготовки этого файла к использованию другим процессом (например, сбросить буферы кэша) и затем удалить или снизить условия аренды. Аренда удаляется по команде \fBF_SETLEASE\fP с аргументом \fIarg\fP, установленным в \fBF_UNLCK\fP. Если арендатор удерживает аренду на запись в файл, и нарушитель аренды открывает файл на чтение, то достаточно того, что арендатор понизит условия аренды до аренды на чтение. Это выполняется командой \fBF_SETLEASE\fP с аргументом \fIarg\fP, установленным в \fBF_RDLCK\fP. .PP Если арендатор не освободит аренду или не снизит условия в течении определённого количества секунд, указанного в файле \fI/proc/sys/fs/lease\-break\-time\fP, то ядро принудительно удалит или снизит условия аренды для арендатора. .PP После того, как был начат разрыв аренды, \fBF_GETLEASE\fP возвращает тип назначения аренды (или \fBF_RDLCK\fP или \fBF_UNLCK\fP, в зависимости от необходимости совместимости с нарушителем аренды) до тех пор, пока держатель аренды добровольно не отдаст или не удалит аренду или ядро принудительно не сделает это после истечения таймера разрыва аренды. .PP После того как аренда снята держателем аренды или принудительно удалена и снижены условия, и предполагая, что нарушитель аренды не выполнял неблокирующий системный вызов, ядро позволяет продолжить работу системного вызова нарушителя аренды. .PP Если нарушитель аренды, заблокированный в \fBopen\fP(2) или \fBtruncate\fP(2), прерывается обработчиком сигнала, то системный вызов завершается неудачно с ошибкой \fBEINTR\fP, но другие шаги по\-прежнему выполняются как описано ранее. Если нарушитель аренды завершается по сигналу будучи блокированным в \fBopen\fP(2) или \fBtruncate\fP(2), то другие шаги по\-прежнему выполняются как описано ранее. Если нарушитель аренды указал флаг \fBO_NONBLOCK\fP при вызове \fBopen\fP(2), то вызов немедленно завершается неудачей с ошибкой \fBEWOULDBLOCK\fP, но другие шаги по\-прежнему выполняются как описано ранее. .PP По умолчанию, для уведомления арендатора используется сигнал \fBSIGIO\fP, но его можно изменить, используя команду \fBF_SETSIG\fP для \fBfcntl\fP(). Если выполняется команда \fBF_SETSIG\fP (даже назначая сигнал \fBSIGIO\fP), и при этом обработчик сигнала устанавливается с использованием \fBSA_SIGINFO\fP, то обработчик получит в качестве второго аргумента структуру \fIsiginfo_t\fP, в которой поле \fIsi_fd\fP будет содержать файловый дескриптор арендованного файла, к которому пытается получить доступ другой процесс (это полезно, если вызывающий процесс удерживает аренду на несколько файлов). .SS "Уведомления об изменении файла и каталога (dnotify)" .TP \fBF_NOTIFY\fP (\fIint\fP) (Начиная с Linux 2.4) Уведомлять при смене каталога, на который указывает \fIfd\fP или когда изменились файлы, которые в нём содержатся. События, о наступлении которых делается уведомление, задаются в аргументе \fIarg\fP, который является битовой маской, получаемой сложением (OR) одного или более следующих бит: .PP .RS .PD 0 .TP \fBDN_ACCESS\fP Был произведён доступ к файлу (\fBread\fP(2), \fBpread\fP(2), \fBreadv\fP(2) и подобные). .TP \fBDN_MODIFY\fP Файл был изменён (\fBwrite\fP(2), \fBpwrite\fP(2), \fBwritev\fP(2), \fBtruncate\fP(2), \fBftruncate\fP(2) и подобные). .TP \fBDN_CREATE\fP Файл был создан (\fBopen\fP(2), \fBcreat\fP(2), \fBmknod\fP(2), \fBmkdir\fP(2), \fBlink\fP(2), \fBsymlink\fP(2), \fBrename\fP(2) в этом каталоге). .TP \fBDN_DELETE\fP Файл был удалён (\fBunlink\fP(2), \fBrename\fP(2) в другой каталог, \fBrmdir\fP(2)). .TP \fBDN_RENAME\fP Файл был переименован внутри каталога (\fBrename\fP(2)). .TP \fBDN_ATTRIB\fP У файла были изменены атрибуты (\fBchown\fP(2), \fBchmod\fP(2), \fButime\fP(2), \fButimensat\fP(2) и подобные). .PD .RE .IP (Чтобы получить эти определения, нужно задать макрос тестирования свойств \fB_GNU_SOURCE\fP перед \fIвсеми\fP остальными заголовочными файлами.) .IP Уведомления об изменении состояния каталога обычно однократные и приложение должно перерегистрировать установку уведомлений, чтобы и дальше получать их. Однако, если в аргумент \fIarg\fP, добавить \fBDN_MULTISHOT\fP, то уведомления будут приходить до тех пор, пока не будут явно отменены. .IP .\" The following does seem a poor API-design choice... Серии запросов \fBF_NOTIFY\fP добавляются к событиям в \fIarg\fP, которые уже установлены. Чтобы выключить уведомления всех событий, выполните вызов \fBF_NOTIFY\fP, указав 0 в \fIarg\fP. .IP Уведомление происходит посредством доставки сигнала. Сигналом по умолчанию является \fBSIGIO\fP, но это можно изменить с помощью команды \fBF_SETSIG\fP \fBfcntl\fP() (заметим, что \fBSIGIO\fP — один из безочерёдных стандартных сигналов; переход к использованию сигнала реального времени означает, что многократные уведомления могут попасть в очередь процесса). В последнем случае, обработчик сигнала принимает структуру \fIsiginfo_t\fP в качестве второго аргумента (если обработчик был установлен с помощью \fBSA_SIGINFO\fP), в поле \fIsi_fd\fP этой структуры содержится файловый описатель, для которого сгенерировано уведомление (полезно при учёте уведомлений из нескольких каталогов). .IP Кроме того, когда используется \fBDN_MULTISHOT\fP, для уведомлений должен бы быть использован сигнал реального времени, так что множественные уведомления могут быть поставлены в очередь. .IP \fBЗАМЕЧАНИЕ:\fP В новых приложениях нужно использовать интерфейс \fIinotify\fP (доступен начиная с ядра 2.6.13), который предоставляет намного лучший интерфейс для получения уведомлений о событиях в файловой системе. Смотрите \fBinotify\fP(7). .SS "Изменение ёмкости канала" .TP \fBF_SETPIPE_SZ\fP (\fIint\fP; начиная с Linux 2.6.35) Изменяет ёмкость канала, на который указывает \fIfd\fP; она становится равной не менее \fIarg\fP байт. Непривилегированный процесс может задать ёмкость канала любого значения, начиная с размера системной страницы до ограничения, заданного в \fI/proc/sys/fs/pipe\-max\-size\fP (смотрите \fBproc\fP(5)). При задании ёмкости меньше размера страницы, она будет без ошибок округлена до размера страницы. При задании непривилегированным процессом ёмкости канала больше ограничения из \fI/proc/sys/fs/pipe\-max\-size\fP приведёт к ошибке \fBEPERM\fP; привилегированный процесс (с \fBCAP_SYS_RESOURCE\fP) может превысить это ограничение. .IP При выделении буфера под канал ядро может использовать большую ёмкость чем указано в \fIarg\fP, если это удобно для реализации (в текущей реализации размером выделения является следующий кратный степени двойки размер страницы больший запрашиваемого размера). Реальным размером (в байтах) считается возвращаемый результат функции. .IP Попытка задать ёмкость канала меньшую размера буферного пространства, используемого в данный момент для хранения данных в канале приводит к ошибке \fBEBUSY\fP. .IP Заметим, что из\-за способа использования страниц буфера канала при записи данных количество байт, которые могут быть записаны, может быть меньше, чем номинальный размер, в зависимости от размера записей. .TP \fBF_GETPIPE_SZ\fP (\fIvoid\fP; начиная с Linux 2.6.35) .\" Возвращает (как результат функции) ёмкость канала, указываемого \fIfd\fP. .SS "Опечатывание файла (file sealing)" Опечатывание файла позволяет ограничить набор выполняемых над файлом операций. Любая операция с файлом, попавшая в набор опечатанных, завершается с ошибкой \fBEPERM\fP. Набор печатей по умолчанию зависит от типа файла, к которому он применяется и файловой системы. Описание опечатывания файла, предназначение и примеры кода смотрите в \fBmemfd_create\fP(2). .PP В настоящее время опечатывание файла может применяться к файловому дескриптору, возвращаемому \fBmemfd_create\fP(2) (если был указан \fBMFD_ALLOW_SEALING\fP). В других файловых системах все операции \fBfcntl\fP(), относящиеся к печатям, возвращают \fBEINVAL\fP. .PP Печати (seals) — свойство inode. То есть все открытые файловые дескрипторы, указывающие на один inode, имеют общий набор печатей. Кроме этого, печати нельзя удалять, можно только добавлять. .TP \fBF_ADD_SEALS\fP (\fIint\fP; начиная с Linux 3.17) Добавляет печати из значения битовой маски \fIarg\fP в набор печатей inode, на которую ссылается файловый дескриптор \fIfd\fP. Печати из набора нельзя удалить. После успешного выполнения, печати сразу же учитываются ядром. Если в текущий набор печатей входит \fBF_SEAL_SEAL\fP (смотрите далее), то этот вызов завершается с ошибкой \fBEPERM\fP. Добавление уже установленной печати ни к чему не приводит, если ещё не указана \fBF_SEAL_SEAL\fP. Чтобы разместить печать файловый дескриптор \fIfd\fP должен быть доступен на запись. .TP \fBF_GET_SEALS\fP (\fIvoid\fP; начиная с Linux 3.17) Возвращает (в виде результата функции) текущий набор печатей inode, на которую указывает \fIfd\fP. Если печатей нет, возвращается 0. Если файл не поддерживает опечатывание, то возвращается \-1 и \fIerrno\fP присваивается \fBEINVAL\fP. .PP Доступны следующие печати: .TP \fBF_SEAL_SEAL\fP Если печать установлена, то последующий вызов \fBfcntl\fP() с \fBF_ADD_SEALS\fP завершится ошибкой \fBEPERM\fP. Таки образом, данная печать предотвращает изменения самого набора печатей. Если начальный набор печатей файла содержит \fBF_SEAL_SEAL\fP, то он является постоянным и неизменяемым. .TP \fBF_SEAL_SHRINK\fP Если эта печать установлена, то нельзя уменьшить размер файла. Она влияет на \fBopen\fP(2) с флагом \fBO_TRUNC\fP, а также на \fBtruncate\fP(2) и \fBftruncate\fP(2). Эти вызовы завершаются ошибкой \fBEPERM\fP, если пытаются уменьшить файл. Увеличение размера файла по\-прежнему возможно. .TP \fBF_SEAL_GROW\fP Если эта печать установлена, то нельзя увеличить размер файла. Она влияет на \fBwrite\fP(2) за концом файла, \fBtruncate\fP(2), \fBftruncate\fP(2) и \fBfallocate\fP(2). Эти вызовы завершаются ошибкой \fBEPERM\fP, если пытаются увеличить файл. Уменьшение размера файла по\-прежнему возможно. .TP \fBF_SEAL_WRITE\fP .\" One or more other seals are typically used with F_SEAL_WRITE .\" because, given a file with the F_SEAL_WRITE seal set, then, .\" while it would no longer be possible to (say) write zeros into .\" the last 100 bytes of a file, it would still be possible .\" to (say) shrink the file by 100 bytes using ftruncate(), and .\" then increase the file size by 100 bytes, which would have .\" the effect of replacing the last hundred bytes by zeros. .\" Если эта печать установлена, то нельзя изменить содержимое файла. Заметим, что уменьшение или увеличение файла по\-прежнему возможно. То есть данная печать, обычно, используется в комбинации с одной из этих печатей. Данная печать влияет на \fBwrite\fP(2) и \fBfallocate\fP(2) (только для флага \fBFALLOC_FL_PUNCH_HOLE\fP). Эти вызовы завершаются ошибкой \fBEPERM\fP. Кроме этого, попытка создать новое общее, доступное на запись отображение через \fBmmap\fP(2) также завершится ошибкой \fBEPERM\fP. .IP Использование операции \fBF_ADD_SEALS\fP для установки \fBF_SEAL_WRITE\fP завершается ошибкой \fBEBUSY\fP, если существует доступное на запись общее отображение. Такие отображения должны быть удалены перед добавлением данной печати. Кроме этого, если у файла есть асинхронные операции, ожидающие ввода\-вывода (\fBio_submit\fP(2)), то все отложенные операции записи будут отброшены. .TP \fBF_SEAL_FUTURE_WRITE\fP (начиная с Linux 5.1) The effect of this seal is similar to \fBF_SEAL_WRITE\fP, 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 \fBmmap\fP(2) will fail with \fBEPERM\fP. Likewise, an attempt to write to the file via \fBwrite\fP(2) will fail with \fBEPERM\fP. .IP .\" 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. .SS "Подсказки чтения/записи файла" Подсказки срока службы записи можно использовать для уведомления ядра об относительно ожидаемом сроке службы записи заданной иноды и открытого файлового описания (об открытых файловых описаниях читайте в \fBopen\fP(2)). В этом контексте термин «срок службы записи» (write lifetime) означает ожидаемое время, которое будут существовать данные на носителе до их перезаписи или стирания. .PP В приложении можно использовать различные значения подсказок, перечисленные ниже, для разделения записей на различные классы, чтобы несколько пользователей или приложений, работающие на одном аппаратном хранилище могли объединить свои шаблоны ввода\-вывода в непротиворечивую форму. Однако, для флагов не подразумевается какая\-то функциональная семантика, и для различных классов ввода\-вывода можно использовать подсказки срока службы записи произвольным образом, пока подсказки не противоречат друг другу. .PP Следующие операции могут применяться к файловому дескриптору \fIfd\fP: .TP \fBF_GET_RW_HINT\fP (\fIuint64_t *\fP; начиная с Linux 4.13) Возвращает значение подсказки чтения/записи, связанной с инодой, на которую указывает \fIfd\fP. .TP \fBF_SET_RW_HINT\fP (\fIuint64_t *\fP; начиная с Linux 4.13) Изменяет значение подсказки чтения/записи, связанной с инодой, на которую указывает \fIfd\fP. Данная подсказка действует до тех пор, пока не будет явно изменена или не будет размонтирована нижележащая файловая система. .TP \fBF_GET_FILE_RW_HINT\fP (\fIuint64_t *\fP; начиная с Linux 4.13) Возвращает значение подсказки чтения/записи, связанной с открытым файловым описанием, на которое указывает \fIfd\fP. .TP \fBF_SET_FILE_RW_HINT\fP (\fIuint64_t *\fP; начиная с Linux 4.13) Изменяет значение подсказки чтения/записи, связанной с открытым файловым описанием, на которое указывает \fIfd\fP. .PP Если открытому файловому описанию не была назначена подсказка чтения/записи, то будет использоваться значение (если есть), назначенное иноде. .PP Начиная с Linux 4.13, действуют следующие подсказки чтения/записи: .TP \fBRWH_WRITE_LIFE_NOT_SET\fP Подсказка не задана. Это значение по умолчанию. .TP \fBRWH_WRITE_LIFE_NONE\fP Срока службы записи, связанного с этим файлом или инодой, не задано. .TP \fBRWH_WRITE_LIFE_SHORT\fP Ожидается, что данные, записанные в эту иноду или через открытое файловое описание, будут иметь короткий срок службы. .TP \fBRWH_WRITE_LIFE_MEDIUM\fP Ожидается, что данные, записанные в эту иноду или через открытое файловое описание, будут иметь срок службы длиннее, чем данные, записанные с \fBRWH_WRITE_LIFE_SHORT\fP. .TP \fBRWH_WRITE_LIFE_LONG\fP Ожидается, что данные, записанные в эту иноду или через открытое файловое описание, будут иметь срок службы длиннее, чем данные, записанные с \fBRWH_WRITE_LIFE_MEDIUM\fP. .TP \fBRWH_WRITE_LIFE_EXTREME\fP Ожидается, что данные, записанные в эту иноду или через открытое файловое описание, будут иметь срок службы длиннее, чем данные, записанные с \fBRWH_WRITE_LIFE_LONG\fP. .PP Все подсказки записи соотносятся друг с другом и нет отдельного абсолютного смысла им предписываемого. .SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" При успешном выполнении возвращаемое значение зависит от используемой команды: .TP \fBF_DUPFD\fP Новый файловый дескриптор. .TP \fBF_GETFD\fP Значение флагов файлового дескриптора. .TP \fBF_GETFL\fP Значение флагов состояния файла. .TP \fBF_GETLEASE\fP Тип аренды, установленной на файлом дескрипторе. .TP \fBF_GETOWN\fP Значение, представляющее собой владельца файлового дескриптора. .TP \fBF_GETSIG\fP Значение сигнала, посылаемого когда становится возможным чтение или запись или ноль для традиционного поведения \fBSIGIO\fP. .TP \fBF_GETPIPE_SZ\fP, \fBF_SETPIPE_SZ\fP Ёмкость канала. .TP \fBF_GET_SEALS\fP Битовая маска, описывающая печати inode, на которую указывает \fIfd\fP. .TP Все остальные команды Ноль. .PP В случае ошибки возвращается \-1 и значение \fIerrno\fP устанавливается соответствующим образом. .SH ОШИБКИ .TP \fBEACCES\fP или \fBEAGAIN\fP Операция запрещена блокировками, которые удерживаются другими процессами. .TP \fBEAGAIN\fP Операция запрещена, потому что файл отображается в память другим процессом. .TP \fBEBADF\fP Значение \fIfd\fP не является открытым файловым дескриптором. .TP \fBEBADF\fP Значение \fIcmd\fP равно \fBF_SETLK\fP или \fBF_SETLKW\fP, но режим открытия файлового дескриптора не совпадает с типом запрошенной блокировки. .TP \fBEBUSY\fP Значение \fIcmd\fP равно \fBF_SETPIPE_SZ\fP и новая ёмкость канала, указанная в \fIarg\fP, меньше размера буферного пространства, используемого в данный момент для хранения данных в канале. .TP \fBEBUSY\fP Значение \fIcmd\fP равно \fBF_ADD_SEALS\fP, в \fIarg\fP содержится \fBF_SEAL_WRITE\fP и существует доступное на запись, общее отображение файла, на который указывает \fIfd\fP. .TP \fBEDEADLK\fP Было обнаружено, что указанная команда \fBF_SETLKW\fP привела бы к взаимной блокировке (deadlock). .TP \fBEFAULT\fP Значение \fIlock\fP находится за пределами доступного адресного пространства. .TP \fBEINTR\fP Значение \fIcmd\fP равно \fBF_SETLKW\fP или \fBF_OFD_SETLKW\fP и операция была прервана сигналом; смотрите \fBsignal\fP(7)). .TP \fBEINTR\fP Значение \fIcmd\fP равно \fBF_GETLK\fP, \fBF_SETLK\fP, \fBF_OFD_GETLK\fP или \fBF_OFD_SETLK\fP и операция была прервана сигналом перед тем как блокировка была проверена или установлена. Большинство таких ошибок случается при блокировке удалённого файла (например, блокировка через NFS), но иногда такое может случаться и с локальным файлом. .TP \fBEINVAL\fP Значение \fIcmd\fP не распознано ядром. .TP \fBEINVAL\fP Значение \fIcmd\fP равно \fBF_ADD_SEALS\fP и \fIarg\fP содержит бит не распознанной печати. .TP \fBEINVAL\fP Значение \fIcmd\fP равно \fBF_ADD_SEALS\fP или \fBF_GET_SEALS\fP и файловая система, содержащая inode, на которую указывает \fIfd\fP, не поддерживает опечатывание. .TP \fBEINVAL\fP Значение \fIcmd\fP равно \fBF_DUPFD\fP и значение \fIarg\fP отрицательное или больше максимально возможного значения (смотрите описание \fBRLIMIT_NOFILE\fP в \fBgetrlimit\fP(2)). .TP \fBEINVAL\fP Значение \fIcmd\fP равно \fBF_SETSIG\fP и значение \fIarg\fP не содержит допустимый номер сигнала. .TP \fBEINVAL\fP Значение \fIcmd\fP равно \fBF_OFD_SETLK\fP, \fBF_OFD_SETLKW\fP или \fBF_OFD_GETLK\fP, но значение \fIl_pid\fP не равно нулю. .TP \fBEMFILE\fP Значение \fIcmd\fP равно \fBF_DUPFD\fP и было достигнуто ограничение по количеству открытых файловых дескрипторов на процесс. .TP \fBENOLCK\fP Открыто слишком много блокировок сегментов, таблица блокировок заполнена или ошибка протокола удалённой блокировки (например, при блокировке через NFS). .TP \fBENOTDIR\fP Значение \fIcmd\fP равно \fBF_NOTIFY\fP, \fIfd\fP не ссылается на каталог. .TP \fBEPERM\fP Значение \fIcmd\fP равно \fBF_SETPIPE_SZ\fP и достигнуто мягкое или жёсткое ограничение канала пользователя; смотрите \fBpipe\fP(7). .TP \fBEPERM\fP Попытка сбросить флаг \fBO_APPEND\fP на файле, который открыт с атрибутом только для добавления. .TP \fBEPERM\fP Значение \fIcmd\fP равно \fBF_ADD_SEALS\fP, но \fIfd\fP не открыт на запись или текущий набор печатей файла уже содержит \fBF_SEAL_SEAL\fP. .SH "СООТВЕТСТВИЕ СТАНДАРТАМ" SVr4, 4.3BSD, POSIX.1\-2001. В POSIX.1\-2001 указаны только команды \fBF_DUPFD\fP, \fBF_GETFD\fP, \fBF_SETFD\fP, \fBF_GETFL\fP, \fBF_SETFL\fP, \fBF_GETLK\fP, \fBF_SETLK\fP и \fBF_SETLKW\fP. .PP .\" .BR _BSD_SOURCE , .\" or Значения \fBF_GETOWN\fP и \fBF_SETOWN\fP определены в POSIX.1\-2001. Для получения их определений, определите \fB_XOPEN_SOURCE\fP со значением 500 или больше или \fB_POSIX_C_SOURCE\fP со значением 200809L или больше. .PP \fBF_DUPFD_CLOEXEC\fP указана в POSIX.1\-2008. Для получения определения, определите \fB_POSIX_C_SOURCE\fP со значением 200809L или больше, или \fB_XOPEN_SOURCE\fP со значением 700 или больше. .PP .\" .PP .\" SVr4 documents additional EIO, ENOLINK and EOVERFLOW error conditions. Команды \fBF_GETOWN_EX\fP, \fBF_SETOWN_EX\fP, \fBF_SETPIPE_SZ\fP, \fBF_GETPIPE_SZ\fP, \fBF_GETSIG\fP, \fBF_SETSIG\fP, \fBF_NOTIFY\fP, \fBF_GETLEASE\fP и \fBF_SETLEASE\fP есть только в Linux. Для задействования этих определений определите макрос \fB_GNU_SOURCE\fP. .PP Значения \fBF_OFD_SETLK\fP, \fBF_OFD_SETLKW\fP и \fBF_OFD_GETLK\fP есть только в Linux (и для получения их определений нужно определить \fB_GNU_SOURCE\fP), но ведётся работа по их включению в следующую версию POSIX.1. .PP .\" FIXME . Once glibc adds support, add a note about FTM requirements Значения \fBF_ADD_SEALS\fP и \fBF_GET_SEALS\fP есть только в Linux. .SH ЗАМЕЧАНИЯ .\" Ошибки, возвращаемые \fBdup2\fP(2), отличаются от тех, что возвращаются при \fBF_DUPFD\fP. .SS "Файловая блокировка" .\" Первоначальная версия системного вызова \fBfcntl\fP() в Linux не умела работать с большими файловыми смещениями (в структуре \fIflock\fP). Позднее, в Linux 2.4 был добавлен системный вызов \fBfcntl64\fP(). Новый системный вызов использует другую структуру для блокировки файлов — \fIflock64\fP и соответствующие команды — \fBF_GETLK64\fP, \fBF_SETLK64\fP и \fBF_SETLKW64\fP. Однако, это различие может игнорироваться приложениями, которые используют glibc, так как имеющаяся в ней обёрточная функция \fBfcntl\fP() самостоятельно задействует более новый системный вызов, если он доступен. .SS "Обычные блокировки (Record locks)" Начиная с ядра 2.0, не существует разницы между типами блокировки, которые осуществляют \fBflock\fP(2) и \fBfcntl\fP(). .PP .\" e.g., Solaris 8 documents this field in fcntl(2), and Irix 6.5 .\" documents it in fcntl(5). mtk, May 2007 .\" Also, FreeBSD documents it (Apr 2014). Некоторые системы имеют дополнительные поля в структуре \fIstruct flock\fP, например, \fIl_sysid\fP (признак машины, на которой удерживается блокировка). Вообще говоря, один \fIl_pid\fP не очень полезен, если процесс, удерживающий блокировку, может работать на другой машине; в Linux, хотя это поле и есть на некоторых архитектурах (например, MIPS32), но оно не используется. .PP Первоначальная версия системного вызова \fBfcntl\fP() в Linux не умела работать с большими файловыми смещениями (в структуре \fIflock\fP). Позднее, в Linux 2.4 был добавлен системный вызов \fBfcntl64\fP(). Новый системный вызов использует другую структуру для блокировки файлов — \fIflock64\fP и соответствующие команды — \fBF_GETLK64\fP, \fBF_SETLK64\fP и \fBF_SETLKW64\fP. Однако, это различие может игнорироваться приложениями, которые используют glibc, так как имеющаяся в ней обёрточная функция \fBfcntl\fP() самостоятельно задействует более новый системный вызов, если он доступен. .SS "Блокировка и NFS" .\" .\" Neil Brown: With NFSv3 the failure mode is the reverse. If .\" the server loses contact with a client then any lock stays in place .\" indefinitely ("why can't I read my mail"... I remember it well). .\" .\" .\" Jeff Layton: .\" Note that this is not a firm timeout. The server runs a job .\" periodically to clean out expired stateful objects, and it's likely .\" that there is some time (maybe even up to another whole lease period) .\" between when the timeout expires and the job actually runs. If the .\" client gets a RENEW in there within that window, its lease will be .\" renewed and its state preserved. .\" До Linux 3.12, если клиент NFSv4 теряет связь с сервером на некоторый период времени (более 90 секунд), то он может потерять и перезапросить блокировки даже не зная об этом (период времени, после которого контакт предполагается потерянным в NFSv4 называется время аренды (leasetime). У Linux в сервере NFS его можно узнать по значению в \fI/proc/fs/nfsd/nfsv4leasetime\fP, которое отражает период в секундах. В этом файле значение по умолчанию равно 90). Данный сценарий несёт потенциальный риск повреждения данных, так как в этот перерыв другой процесс может установить блокировку и выполнить файловый ввод\-вывод. .PP .\" commit ef1820f9be27b6ad158f433ab38002ab8131db4d .\" commit f6de7a39c181dfb8a2c534661a53c73afb3081cd Начиная с Linux 3.12, если клиент NFSv4 теряет контакт с сервером, то любой файловый ввод\-вывод, выполняемый процессом, который «думает», что имеет блокировку, будет завершаться с ошибкой до тех пор, пока этот процесс не закроет и не переоткроет файл. Чтобы вернуть поведение, которое было до версии pre\-3.12, можно параметру ядра \fInfs.recover_lost_locks\fP присвоить значение 1, из\-за чего клиент буде пытаться восстановить потерянные блокировки при переустановлении связи с сервером. Из\-за наличия сопутствующего риска повреждения данных, значение данного параметра по умолчанию равно 0 (отключено). .SH ДЕФЕКТЫ .SS F_SETFL .\" FIXME . According to POSIX.1-2001, O_SYNC should also be modifiable .\" via fcntl(2), but currently Linux does not permit this .\" See http://bugzilla.kernel.org/show_bug.cgi?id=5994 Невозможно использовать \fBF_SETFL\fP для смены состояния флагов \fBO_DSYNC\fP и \fBO_SYNC\fP. Попытка изменить состояние этих флагов просто игнорируется. .SS F_GETOWN .\" glibc source: sysdeps/unix/sysv/linux/i386/sysdep.h .\" mtk, Dec 04: some limited testing on alpha and ia64 seems to .\" indicate that ANY negative PGID value will cause F_GETOWN .\" to misinterpret the return as an error. Some other architectures .\" seem to have the same range check as i386. Ограничение в соглашениях по системным вызовам Linux на некоторых архитектурах (в частности i386) приводит к тому, что если значение ID группы процесса (отрицательное), возвращаемое по команде \fBF_GETOWN\fP, попадает в диапазон от \-1 до \-4095, то оно неправильно интерпретируется glibc и считается ошибкой в системном вызове; то есть возвращаемое значение \fBfcntl\fP() будет равно \-1, а \fIerrno\fP будет содержать значение ID группы процесса (положительное). Команда \fBF_GETOWN_EX\fP (есть только в Linux) не подвержена этой проблеме. Начиная с glibc версии 2.11, glibc делает проблему для \fBF_GETOWN\fP невидимой, реализовав \fBF_GETOWN\fP с помощью \fBF_GETOWN_EX\fP. .SS F_SETOWN .\" В Linux 2.4 и более раннем, есть ошибка, которая может произойти когда непривилегированный процесс использует \fBF_SETOWN\fP для задания владельца дескриптора файла сокета как процесса (группу) отличного от вызывающего. В этом случае \fBfcntl\fP() может вернуть \-1 с \fIerrno\fP равным \fBEPERM\fP, даже когда процесс (группа) владелец такая же как и вызывающий имеет право посылать сигнал. Несмотря на возвращаемую ошибку, владелец файлового дескриптора всё равно устанавливается и сигналы будут посылаться владельцу. .SS "Обнаружение взаимных блокировок (deadlock)" .\" Алгоритм обнаружения взаимных блокировок задействуется ядром при работе с запросами \fBF_SETLKW\fP и может закончиться как ненахождением (не удалось обнаружить взаимную блокировку и процессы блокируют друг друга навсегда), так и ошибочным нахождением (ошибка \fBEDEADLK\fP, но взаимная блокировка отсутствует). Например, ограничение ядра на вложенность зависимостей блокировки при поиске равна 10, что означает, что цепочки циклических зависимостей, превышающие этот размер, не будут обнаружены. Также ядро может ошибочно посчитать за взаимную блокировку ситуацию, когда два и более процесса, созданных с помощью \fBclone\fP(2) с флагом \fBCLONE_FILES\fP, размещают блокировки, которые похожи (для ядра) на конфликтующие. .SS "Обязательная (mandatory) блокировка" .\" http://marc.info/?l=linux-kernel&m=119013491707153&w=2 .\" .\" Reconfirmed by Jeff Layton .\" From: Jeff Layton redhat.com> .\" Subject: Re: Status of fcntl() mandatory locking .\" Newsgroups: gmane.linux.file-systems .\" Date: 2014-04-28 10:07:57 GMT .\" http://thread.gmane.org/gmane.linux.file-systems/84481/focus=84518 Реализация обязательной блокировки в Linux проводит к состязательности процессов, что делает её ненадёжной: вызов \fBwrite\fP(2), пересекающийся с блокировкой, может изменить данные после установления обязательной блокировки; вызов \fBread\fP(2), пересекающийся с блокировкой, может обнаружить изменившиеся данные, которые были внесены уже установления блокировки на запись. Подобная состязательность существует между обязательными блокировками и \fBmmap\fP(2). Поэтому нецелесообразно полагаться на обязательную блокировку. .SH "СМ. ТАКЖЕ" \fBdup2\fP(2), \fBflock\fP(2), \fBopen\fP(2), \fBsocket\fP(2), \fBlockf\fP(3), \fBcapabilities\fP(7), \fBfeature_test_macros\fP(7), \fBlslocks\fP(8) .PP Файлы \fIlocks.txt\fP, \fImandatory\-locking.txt\fP и \fIdnotify.txt\fP из каталога \fIDocumentation/filesystems.\fP исходного кода ядра Linux (в старых ядрах эти файлы были в каталоге \fIDocumentation/\fP, а \fImandatory\-locking.txt\fP назывался \fImandatory.txt\fP). .SH ЗАМЕЧАНИЯ Эта страница является частью проекта Linux \fIman\-pages\fP версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу \%https://www.kernel.org/doc/man\-pages/. .PP .SH ПЕРЕВОД Русский перевод этой страницы руководства был сделан Azamat Hackimov , Dmitry Bolkhovskikh , Yuri Kozlov и Иван Павлов . .PP Этот перевод является бесплатной документацией; прочитайте .UR https://www.gnu.org/licenses/gpl-3.0.html Стандартную общественную лицензию GNU версии 3 .UE или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ. .PP Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на .MT man-pages-ru-talks@lists.sourceforge.net .ME .