Scroll to navigation

OPEN(2) Руководство программиста Linux OPEN(2)

ИМЯ

open, creat - открывает и, возможно, создаёт файл или устройство

ОБЗОР

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);

ОПИСАНИЕ

Получив в pathname имя файла, open() возвращает файловый дескриптор — небольшое, неотрицательное значение — для использования в последующих системных вызовах (read(2), write(2), lseek(2), fcntl(2) и т.д.). Файловый дескриптор, возвращаемый при успешном выполнении вызова, будет самым маленьким числом из файловых дескрипторов, которые ещё не открыты процессом.

По умолчанию, новый файловый дескриптор остаётся открытым при вызове execve(2) (т.е., флаг FD_CLOEXEC файлового дескриптора, описанный в fcntl(2), изначально сброшен; для изменения поведения по умолчанию можно использовать флаг O_CLOEXEC, он описан далее). Файловое смещение устанавливается на начало файла (см. lseek(2)).

Вызов open() создаёт новое открытое файловое описание — запись в системной таблице открытых файлов. В этой записи хранится смещение и флаги состояния файла (изменяются через fcntl(2), операция F_SETFL). Файловый дескриптор является ссылкой на одну из таких записей; с этой ссылкой ничего не происходит при последующем удалении имени файла или переуказании имени на другой файл. Изначально, новое открытое файловое описание не используется разными процессами совместно, но такого общего использования можно достичь, вызвав fork(2).

Параметр flags должен содержать один из следующих режимов доступа: O_RDONLY (только для чтения), O_WRONLY (только для записи) или O_RDWR (для чтения и записи).

Кроме них в flags можно указывать флаги создания и состояния файла, объединяя их битовой операцией ИЛИ. Флаги создания файла: O_CREAT, O_EXCL, O_NOCTTY и O_TRUNC. Флаги состояния файла — все оставшиеся из перечисленных ниже. Различие между двумя этими группами в том, что флаги состояния можно запросить и (в некоторых случаях) изменить с помощью fcntl(2). Вот полный список флагов создания и состояния файла:

Файл открывается в режиме добавления. Перед каждым вызовом write(2) файловое смещение устанавливается в конец файла, как если бы это делалось с помощью lseek(2). Флаг O_APPEND может приводить к повреждению файлов в файловой системе NFS, если одновременно добавляют данные в файл несколько процессов. Это происходит из-за того, что NFS не поддерживает добавление в файл, поэтому клиентское ядро имитирует такое поведение, но при этом нельзя избежать состязательности процессов.
Включает ввод-вывод, управляемый сигналом: генерирует сигнал (по умолчанию SIGIO, но можно изменить с помощью fcntl(2)), когда становится возможным ввод или вывод для этого файлового дескриптора. Эта возможность доступна только для терминалов, псевдо-терминалов, сокетов, каналов (начиная с Linux 2.6) и FIFO. Подробней см. fcntl(2).
Устанавливает флаг close-on-exec на новом файловом дескрипторе. Указание данного флага позволяет программе избежать дополнительных операций fcntl(2) F_SETFD для установки флага FD_CLOEXEC. Также, использование этого флага обязательно для некоторых многонитиевых программ, так как использование отдельной операции fcntl(2) F_SETFD для установки флага FD_CLOEXEC недостаточно для избежания состязательности, когда одна нить открывает файловый дескриптор, а в тоже время другая нить может выполнять fork(2) и execve(2).
Если файл не существует, то он будет создан. Владелец (идентификатор пользователя) файла устанавливается в значение эффективного идентификатора пользователя процесса. Группа (идентификатор группы) устанавливается либо в значение эффективного идентификатора группы процесса, либо в значение идентификатора группы родительского каталога (зависит от типа файловой системы, параметров монтирования и режима родительского каталога, см. например, параметры монтирования bsdgroups и sysvgroups, описанные в mount(8)).

В аргументе mode указываются права использования, которые используются при создании нового файла. Этот параметр должен указываться, если в flags устанавливается O_CREAT; если O_CREAT не задан, то mode игнорируется. Эффективные права изменяются согласно umask процесса как обычно: права созданного файла будут установлены согласно (mode & ~umask). Заметим, что этот режим будет учтён только при последующих обращениях к созданному файлу; вызов open(), создающий файл только для чтения, может вернуть файловый дескриптор доступный на чтение и запись.

Символьные константы, используемые в mode:

00700 пользователь (владелец файла) имеет права на чтение, запись и выполнение файла
00400 пользователь имеет права на чтение файла
00200 пользователь имеет права на запись в файл
00100 пользователь имеет права на выполнение файла
00070 группа имеет права на чтение, запись и выполнение файла
00040 группа имеет права на чтение файла
00020 группа имеет права на запись в файл
00010 группа имеет права на выполнение файла
00007 все остальные имеют права на чтение, запись и выполнение файла
00004 все остальные имеют права на чтение файла
00002 все остальные имеют права на запись в файл
00001 все остальные имеют права на выполнение файла
O_DIRECT (начиная с Linux 2.4.10)
Попытаться минимизировать влияние кэширования ввода-вывода при чтении и записи в файл. Обычно, это ухудшает производительность, но полезно для особых случаев, например, когда приложение выполняет кэширование самостоятельно. Файловый ввод-вывод выполняется непосредственно в/из буферов пространства пользователя. При флаге O_DIRECT предпринимаются все усилия для синхронной передачи данных, но это не гарантирует, как с флагом O_SYNC, передачу данных и необходимых метаданных. Чтобы гарантировать синхронный ввод-вывод вместе с O_DIRECT нужно использовать O_SYNC. Дальнейшее описание смотрите далее в разделе ЗАМЕЧАНИЯ.

Семантически похожий интерфейс (но устаревший) для блочных устройств описан в raw(8).

Если pathname не является каталогом, то завершить вызов с ошибкой. Этот флаг используется только в Linux и был добавлен в ядро версии 2.1.126, чтобы избежать проблем с «отказом в обслуживании», если opendir(3) был вызван для канала FIFO или ленточного устройства. Этот флаг не следует использовать вне реализации opendir(3).
Гарантирует, что вызов создаст файл: если этот флаг указан вместе с O_CREAT и pathname уже существует, то open() завершится с ошибкой.

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

Вообще говоря, поведение с O_EXCL не определено, если этот флаг используется без O_CREAT. Есть одно исключение: в Linux 2.6 и более новых O_EXCL можно использовать без O_CREAT, если pathname указывает на блочное устройство. Если блочное устройство используется в системе (например, смонтировано), то open() завершится с ошибкой EBUSY.

Флаг O_EXCL поддерживается для NFS только, если используется NFSv3 или новее с ядром 2.6 или новее. В средах, где в NFS нет поддержки O_EXCL, программы, которые полагаются на это для выполнения задач блокировок, будут создавать состязательность процессов. Переносимым программам, которым нужно произвести атомарную блокировку файла с помощь файла блокировки, необходимо избегать зависимости от поддержки в NFS флага O_EXCL. В качестве решения можно создать уникальный файл в той же файловой системе (например, добавив имя узла и PID в название), чтобы создать ссылку на файл блокировки с помощью link(2). Если link(2) возвращает 0, то блокировка выполнена. В противном случае используйте stat(2), чтобы убедиться, что количество ссылок на уникальный файл возросло до двух. Это также означает, что блокировка была успешной.

(LFS) Позволяет открывать файлы, чей размер нельзя представить типом off_t (но можно представить типом off64_t). Для получения этого определения должен быть указан макрос _LARGEFILE64_SOURCE (до включения какого-либо заголовочного файла). Установка макроса тестирования возможностей _FILE_OFFSET_BITS в значение 64 (вместо использования O_LARGEFILE) является предпочтительным методом доступа к большим файлам на 32-битных системах (см. feature_test_macros(7)).
Не обновлять время последнего доступа к файлу (st_atime в inode) при его чтении read(2). Этот флаг предназначен для использования в программах индексирования и резервного копирования; он позволяет значительно сократить количество обращений к диску. Флаг может быть не эффективен на некоторых файловых системах. Например, на NFS, где запись времени доступа выполняется сервером.
Если pathname указывает на терминальное устройство (см. tty(4)), то оно не станет управляющим терминалом процесса, даже если процесс такового не имеет.
Если pathname является символьной ссылкой, то открытие завершится неудачно. Это расширение FreeBSD, которое было добавлено в Linux версии 2.1.126. Все прочие символьные ссылки в имени будут обработаны как обычно.
Если возможно, файл открывается в неблокирующем режиме. Ни open(), ни другие последующие операции над возвращаемым дескриптором файла не заставят вызывающий процесс ждать. Для работы с каналами FIFO также смотрите fifo(7). Обсуждение влияния O_NONBLOCK в сочетании с обязательной файловой блокировкой или арендой (lease) смотрите в fcntl(2).
Файл открывается в режиме синхронного ввода-вывода. Все вызовы write(2) для соответствующего дескриптора файла блокируют вызывающий процесс до тех пор, пока данные не будут физически записаны. Однако, прочитайте раздел ЗАМЕЧАНИЯ.
Если файл уже существует и является обычным файлом и режим открытия позволяет записывать в этот файл (т.е. установлен флаг O_RDWR или O_WRONLY), то его длина будет урезана до нуля. Если файл является FIFO или терминальным устройством, то этот флаг игнорируется. В других случаях действие флага O_TRUNC не определено.

Некоторые из этих необязательных флагов могут быть изменены с помощью fcntl(2) после открытия файла.

Вызов creat() эквивалентен open() с flags, имеющим значение O_CREAT|O_WRONLY|O_TRUNC.

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

Вызовы open() и creat() возвращают новый дескриптор файла или -1 в случае ошибки (в этом случае errno устанавливается в соответствующее значение).

ОШИБКИ

Запрошенный доступ к файлу не разрешён, или один из каталогов в pathname не позволяет поиск, файл ещё не существует, или доступ для записи в родительский каталог не разрешён (см. также path_resolution(7)).
pathname уже существует, то были указаны O_CREAT и O_EXCL.
Аргумент pathname указывает за пределы доступного адресного пространства.
Смотрите EOVERFLOW.
При блокирующем ожидании завершения открытия медленного устройства (например, FIFO; см. fifo(7)), вызов был прерван обработчиком сигнала; смотрите signal(7).
pathname указывает на каталог и тип доступа подразумевает запись ( то есть установлен флаг O_WRONLY или O_RDWR).
Слишком много символьных ссылок пройдено при разрешении pathname, или задан O_NOFOLLOW, но pathname является символьной ссылкой.
Процесс уже открыл максимально допустимое количество файлов.
pathname слишком длинен.
Достигнуто максимальное количество открытых файлов в системе.
pathname ссылается на специальный файл устройства, но соответствующего устройства не существует (это ошибка в ядре Linux: должно возвращаться ENXIO).
Флаг O_CREAT не задан и файл с таким именем не существует, или же не существует один из каталогов в pathname, или имеется повисшая символьная ссылка.
Недостаточное количество памяти ядра.
Файл pathname должен быть создан, но на устройстве его содержащем нет места для нового файла.
Компонент, который обозначен как каталог в pathname, таковым не является, или был указан флаг O_DIRECTORY, но pathname не является каталогом.
Указаны флаги O_NONBLOCK | O_WRONLY, файл является каналом FIFO, но нет процесса, который открыл этот канал для чтения. Возможно также, что файл является специальным файлом устройства, но соответствующее устройство не существует.
pathname ссылается на обычный файл, который слишком велик для открытия. Обычно, это случается когда приложение, скомпилированное на 32-битной платформе без -D_FILE_OFFSET_BITS=64, пытается открыть файл размером более (2<<31)-1 бит; смотрите также описание O_LARGEFILE ранее. Эта ошибка определена в POSIX.1-2001; в ядрах до версии 2.6.24 Linux в этом случае выдавал ошибку EFBIG.
Задан флаг O_NOATIME, но эффективный ID пользователя вызывающего процесса не совпадает с владельцем файла и вызывающий не имеет прав (CAP_FOWNER).
pathname указывает на файл на файловой системе, доступной только на чтение, но запрашивается доступ на запись.
pathname указывает на исполняемый файл, который запущен в данный момент, но запрашивается доступ на запись.
Указан флаг O_NONBLOCK, но несовместимая аренда (lease) удерживает файл (смотрите fcntl(2)).

СООТВЕТСТВИЕ СТАНДАРТАМ

SVr4, 4.3BSD, POSIX.1-2001. Флаги O_DIRECTORY, O_NOATIME и O_NOFOLLOW есть только в Linux, и для их определения может потребоваться задать _GNU_SOURCE (до включения какого-либо заголовочного файла).

Флаг O_CLOEXEC не определён в POSIX.1-2001, но есть в POSIX.1-2008.

Флаг O_DIRECT не определён в POSIX; для его определения задайте _GNU_SOURCE (до включения какого-либо заголовочного файла).

ЗАМЕЧАНИЯ

В Linux флаг O_NONBLOCK указывает, что файл нужно открыть, но не обязательно будет производиться чтение или запись. Обычно это указывается для открытия устройства, чтобы получить его файловый дескриптор для использования в ioctl(2).

В отличие от других значений, указываемых в flags, значения режима доступа O_RDONLY, O_WRONLY и O_RDWR, не определяются отдельными битами. Точнее, они задаются двумя первыми битами flags, и имеют значения 0, 1 и 2, соответственно. Другими словами, комбинация O_RDONLY | O_WRONLY приводит к логической ошибке и точно не работает как O_RDWR. В Linux зарезервирован специальный нестандартный режим доступа 3 (11 двоичное) в flags, при котором: проверяются права на чтение и запись к файлу и возвращается дескриптор, который не может использоваться для чтения или записи. Данный нестандартный режим доступа используется некоторыми драйверами Linux для получения дескриптора, который будет использоваться в ioctl(2) только для специальных операций с устройством.

Результат работы комбинации флагов O_RDONLY | O_TRUNC в разных реализациях разный (нигде не определён). Во многих системах файл усекается.

В протоколе, по которому работает NFS, существует множество недоработок, оказывающих влияние на многое, в том числе на работу с O_SYNC и O_NDELAY.

В POSIX представлено три различных варианта синхронизированного ввода-вывода, соответствующих флагам O_SYNC, O_DSYNC и O_RSYNC. На данный момент (2.6.31) в Linux реализован только O_SYNC, но glibc проецирует O_DSYNC и O_RSYNC в то же числовое значение что и O_SYNC. В большинстве файловых систем Linux, на самом деле, не реализована семантика POSIX O_SYNC, которая требует записи всех обновлённых метаданных на диск до возврата в пространство пользователя, а только семантика O_DSYNC, по которой до возврата из вызова должны быть реально записаны только данные файла и метаданные, необходимые для их получения.

Заметим, что open() может открывать специальные файлы устройств, но creat() не может их создавать; вместо этого используйте mknod(2).

В файловых системах NFS с включённым проецированием UID, open() может вернуть файловый дескриптор, но, например, запросы read(2) будут отклонены с ошибкой EACCES. Это происходит из-за того, что клиент выполняет open() проверяя одни права, но сервер выполняет проецирование UID только при запросах чтения и записи.

Если файл только что был создан, его поля st_atime, st_ctime, st_mtime (время последнего доступа, последней смены состояния и последнего изменения, соответственно; см. stat(2)) устанавливаются в значение текущего времени, и оно совпадает с полями st_ctime и st_mtime родительского каталога. Или же, если файл изменяется из-за установленного флага O_TRUNC, то его поля st_ctime и st_mtime устанавливаются в значение текущего времени.

O_DIRECT

Флаг O_DIRECT может накладывать ограничения по выравниванию на длину и адрес буфера пользовательского пространства и смещения файла при вводе-выводе. В Linux ограничения по выравниванию различны у разных файловых систем и версий ядра, и даже могут отсутствовать. Однако сейчас не существует независимого от файловой системы интерфейса приложения для выявления этих ограничений на определённый файл или файловую систему. Некоторые файловые системы предоставляют свои собственные интерфейсы для этого, например, операция XFS_IOC_DIOINFO в xfsctl(3).

В Linux 2.4 размеры передачи, выравнивание пользовательского буфера и файлового смещения должны быть кратны размеру логического блока файловой системы. В Linux 2.6 достаточно выравнивания по 512-байтовой границе.

Ввод-вывод с O_DIRECT никогда не должен запускаться одновременно с системным вызовом fork(2), если буфер памяти является закрытым отображением (т. е., любым отображениям, созданным с помощью mmap(2) с флагом MAP_PRIVATE; к ним относится память, выделенная под кучу и статически выделенные буферы). Любой подобный ввод-вывод, предоставленный через асинхронный интерфейс или из другой нити процесса, должен выполниться полностью до вызова fork(2). В противном случае, может произойти повреждение данных и непредсказуемое поведение в процессе родителя и потомка.Данное ограничение не действует, если буфер памяти для ввода-вывода с O_DIRECT был создан с помощью shmat(2) или mmap(2) с флагом MAP_SHARED. И при этом это ограничение не действует, когда буфер памяти был помечен (advised) как MADV_DONTFORK с помощью madvise(2), если точно известно, что он не будет доступен потомку после fork(2).

Флаг O_DIRECT появился в SGI IRIX, где ограничения на выравнивание подобны Linux 2.4. В IRIX также есть вызов fcntl(2) для запроса значений соответствующего выравнивания и размеров. В FreeBSD 4.x появился флаг с таким же именем, но без ограничений на выравнивание.

Поддержка O_DIRECT добавлена в ядро Linux версии 2.4.10. Более старые ядра Linux просто игнорируют этот флаг. В некоторых файловых системах этот флаг может быть не реализован и open() завершится с ошибкой EINVAL при его использовании.

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

Поведение O_DIRECT на NFS отличается от локальных файловых систем. Старые ядра и ядра, настроенные определёнными способами, могут не поддерживать такую комбинацию. Протокол NFS не поддерживает передачу флага на сервер, поэтому ввод-вывод с O_DIRECT будет пропускать кэширование страниц только на клиенте; сервер всё равно может выполнить кэширование ввода-вывода. Клиент просит сервер выполнять операции ввода-вывода синхронно для сохранения синхронной семантики O_DIRECT. Некоторые серверы будут выполнять это плохо при определённых условиях, особенно если размер данных ввода-вывод невелик. Некоторые серверы также могут быть настроены на отправку ложного ответа клиентам о том, что ввод-вывод произведён на носитель; это позволяет избежать потери производительности, но есть риск потери целостности данных в случае проблем с электропитанием сервера. В Linux клиент NFS не устанавливает ограничений по выравниванию при вводе-выводе с O_DIRECT.

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

«The thing that has always disturbed me about O_DIRECT is that the whole interface is just stupid, and was probably designed by a deranged monkey on some serious mind-controlling substances.» — Linus (Меня всегда беспокоило кое-что относительно O_DIRECT — то, что вообще в целом этот интерфейс просто идиотичен. Создаётся впечатление, что он как-бы был создан сумасшедшей обезьяной под веществами.)

ДЕФЕКТЫ

На данный момент невозможно включить сигнальное управление вводом-выводом, указав O_ASYNC при вызове open(); чтобы установить этот флаг используйте fcntl(2).

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

chmod(2), chown(2), close(2), dup(2), fcntl(2), link(2), lseek(2), mknod(2), mmap(2), mount(2), openat(2), read(2), socket(2), stat(2), umask(2), unlink(2), write(2), fopen(3), fifo(7), path_resolution(7), symlink(7)

2012-05-01 Linux