Таблица 4.3. Значения для аргументов флагов системного вызова open()
Флаг — Назначение — SUS?
O_RDONLY — Открытие только для чтения — v3
O_WRONLY — Открытие только для записи — v3
O_RDWR — Открытие для чтения и записи — v3
O_CLOEXEC — Установка флага закрытия при выполнении (close-on-exec) (начиная с версии Linux 2.6.23) — v4
O_CREAT — Создание файла, если он еще не существует — v3
O_DIRECTORY — Отказ, если аргумент pathname указывает не на каталог — v4
O_EXCL — С флагом O_CREAT: исключительное создание файла — v3
O_LARGEFILE — Используется в 32-разрядных системах для открытия больших файлов -
O_NOCTTY — Pathname запрещено становиться управляющим терминалом данного процесса — v3
O_NOFOLLOW — Запрет на разыменование символьных ссылок — v4
O_TRUNC — Усечение существующего файла до нулевой длины — v3
O_APPEND — Записи добавляются исключительно в конец файла — v3
O_ASYNC — Генерация сигнала, когда возможен ввод/вывод —
O_DIRECT — Операции ввода-вывода осуществляются без использования кэша —
O_DSYNC — Синхронизированный ввод-вывод с обеспечением целостности данных (начиная с версии Linux 2.6.33) — v3
O_NOATIME — Запрет на обновление времени последнего доступа к файлу при чтении с помощью системного вызова read() (начиная с версии Linux 2.6.8) -
O_NONBLOCK — Открытие в неблокируемом режиме — v3
O_SYNC — Ведение записи в файл в синхронном режиме — v3
Константы в табл. 4.3 разделяются на следующие группы.
• Флаги режима доступа к файлу. Это рассмотренные ранее флаги O_RDONLY, O_WRONLY и O_RDWR. Их можно извлечь с помощью операции F_GETFL функции fcntl() (см. раздел 5.3).
Флаги создания файла. Это флаги, показанные во второй части табл. 4.3. Они управляют различными особенностями поведения системного вызова open(), а также вариантами для последующих операций ввода-вывода. Эти флаги не могут быть извлечены или изменены.
Флаги состояния открытия файла. Это все остальные флаги, показанные в табл. 4.3. Они могут быть извлечены и изменены с помощью операций F_GETFL и F_SETFL функции fcntl() (см. раздел 5.3). Эти флаги иногда называют просто флагами состояния файла.
Начиная с версии ядра 2.6.22, для получения информации о дескрипторах файлов любого имеющегося в системе процесса могут быть прочитаны файлы в каталоге /proc/PID/fdinfo, которые есть только в Linux. В этом каталоге находится по одному файлу для каждого дескриптора открытого процессом файла, с именем, совпадающим с номером дескриптора. В поле pos этого файла показано текущее смещение в файле (см. раздел 4.7). В поле flags находится восьмеричное число, показывающее флаги режима доступа к файлу и флаги состояния открытого файла. (Чтобы декодировать эти числа, нужно посмотреть на числовые значения флагов в заголовочных файлах библиотеки языка C.)
Рассмотрим константы флагов подробнее.
• O_APPEND — записи добавляются исключительно в конец файла. Значение этого флага рассматривается в разделе 5.1.
• O_ASYNC — генерирование сигнала при появлении возможности ввода-вывода с использованием файлового дескриптора, возвращенного системным вызовом open(). Это свойство называется вводом-выводом под управлением сигналов. Оно доступно только для файлов определенного типа, таких как терминалы, FIFO-устройства и сокеты. (Флаг O_ASYNC не определен в SUSv3, но в большинстве реализаций UNIX он или его синоним FASYNC присутствует.) В Linux указание флага O_ASYNC при вызове open() не имеет никакого эффекта. Чтобы включить ввод/вывод с сигнальным управлением, нужно установить этот флаг, указывая в fcntl() операцию F_SETFL (см. раздел 5.3). (Некоторые другие реализации UNIX ведут себя аналогичным образом.) Дополнительные сведения о флаге O_ASYNC можно найти в разделе 59.3.
• O_CLOEXEC (с выходом Linux 2.6.23) — установка флага закрытия при выполнении — флага close-on-exec (FD_CLOEXEC) для нового дескриптора файла. Флаг FD_CLOEXEC рассматривается в разделе 27.4. Использование флага O_CLOEXEC позволяет программе не выполнять дополнительные операции F_GETFD и F_SETFD при вызове fcntl() для установки флага close-on-exec. Кроме того, в многопоточных программах необходимо избегать состояния гонки, возможное при использовании данной технологии. Например, такое состояние может возникать, когда один поток открывает дескриптор файла, а затем пытается пометить его флагом close-on-exec, и в то же самое время другой поток выполняет системный вызов fork(), а затем exec() из какой-нибудь другой программы. (Предположим, что второй поток справляется и с fork(), и с exec() в период между тем, как первый поток открывает файловый дескриптор и использует fcntl() для установки флага close-on-exec.) Такое состязание может привести к тому, что открытые дескрипторы файлов могут непреднамеренно быть переданы небезопасным программам. (Состояние гонки подробнее рассматривается в разделе 5.1.)