В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13 |
Файловый ввод/вывод
Открытие и закрытие файлов
Как уже указывалось, открытие файла должно предшествовать операциям ввода/вывода, поскольку оно возвращает дескриптор файла или поток, которые используют подобные операции. Для открытия файлов и формирования новых описаний открытых файлов, файловых дескрипторов и потоков служат функции нижнего уровня open() и pipe() (см. листинг 5.1), а также функции буферизованного ввода/вывода, показанные в листинге 5.2.
#include <fcntl.h> int open (const char *path, int oflag, ...); #include <unistd.h> int pipe (int fildes [2]);Листинг 5.1. Описание функций open() и pipe().
#include <stdio.h> FILE *fopen (const char *restrict path, const char *restrict mode); #include <stdio.h> FILE *fdopen (int fildes, const char *mode); #include <stdio.h> FILE *freopen (const char *restrict path, const char *restrict mode, FILE *restrict stream);Листинг 5.2. Описание функций fopen(), fdopen(), freopen().
Функция open() открывает файл с заданным маршрутным именем (первый аргумент, path ), создавая для него описание – новое и, следовательно, не разделяемое с другими процессами. Возвращаемый в качестве результата файловый дескриптор является минимальным из числа не используемых в данный момент текущим процессом (при неудаче возвращается -1 ).
Второй аргумент, oflag, устанавливает флаги статуса файла и определяет допустимые виды операций ввода/вывода. Его значение формируется как побитное ИЛИ перечисленных ниже флагов. Из первых трех флагов должен быть задан ровно один.
O_RDONLY
Открыть файл только на чтение.
O_WRONLY
Открыть файл только на запись.
O_RDWR
Открыть файл на чтение и запись.
Следующие флаги могут комбинироваться произвольным образом.
O_APPEND
Перед каждой записью устанавливать индикатор текущей позиции на конец файла.
O_CREAT
Если файл существует, данный флаг принимается во внимание только при наличии описываемого далее флага O_EXCL. Если файла нет, он создается от имени текущего пользователя. Обратим внимание, что функция open() имеет переменное число аргументов. При создании файла предполагается, что в качестве третьего аргумента типа mode_t задается режим доступа.
O_EXCL
Если установлены флаги O_CREAT и O_EXCL, а файл существует (хотя бы и в виде символьной ссылки на несуществующий файл), вызов open() завершится неудачей. Проверка существования файла и его создание представляют собой атомарное действие по отношению к попыткам других процессов ( потоков управления) выполнить аналогичный запрос.
O_TRUNC
Если файл существует, является обычным и успешно открывается с флагами O_RDWR или O_WRONLY, он опустошается (размер устанавливается равным нулю).
Отметим, что рассмотренная ранее функция creat (path, mode) по определению эквивалентна вызову open (path, O_WRONLY | O_CREAT | O_TRUNC, mode).
Следующий флаг относится к асинхронному вводу/выводу.
O_NONBLOCK
Обычно, если канал открывается только на чтение (или только на запись), процесс ( поток управления) блокируется, пока этот же канал не откроют на запись (чтение). При установленном флаге O_NONBLOCK открытие на чтение завершается без задержки, а открытие на запись заканчивается неудачей, если канал еще не открыт кем-либо на чтение.
При открытии специального файла вызов open() завершается только после того, как устройство оказывается в состоянии готовности. Флаг O_NONBLOCK отменяет эту задержку, однако последующее поведе- ние устройства зависит от реализации.
Следующая группа флагов обслуживает синхронизированный ввод/вывод.
O_DSYNC
Операции записи с возвращаемым файловым дескриптором должны завершаться с обеспечением целостности данных.
O_SYNC
Операции записи должны завершаться с обеспечением целостности файла.
O_RSYNC
Операции чтения должны завершаться на уровне целостности, заданном флагами O_DSYNC или O_SYNC.
Смысл последнего из стандартизованных флагов будет пояснен при рассмотрении процессов.
O_NOCTTY
Если открывается специальный файл, соответствующий терминалу, последний не должен становиться управляющим терминалом процесса. Для создания и открытия канала предназначена функция pipe(). В массиве fildes она возвращает сразу два дескриптора: fildes [0] служит для чтения, fildes [1] – для записи. Данные читаются в том же порядке, в каком были записаны.
При успешном завершении pipe() возвращает 0, при неудаче – -1.