Опубликован: 15.06.2004 | Доступ: свободный | Студентов: 2557 / 712 | Оценка: 4.35 / 3.96 | Длительность: 27:47:00
ISBN: 978-5-9556-0011-6
Лекция 5:

Файловый ввод/вывод

Открытие и закрытие файлов

Как уже указывалось, открытие файла должно предшествовать операциям ввода/вывода, поскольку оно возвращает дескриптор файла или поток, которые используют подобные операции. Для открытия файлов и формирования новых описаний открытых файлов, файловых дескрипторов и потоков служат функции нижнего уровня 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.

Антон Коновалов
Антон Коновалов

В настоящее время актуальный стандарт - это POSIX 2008 и его дополнение POSIX 1003.13
Планируется ли актуализация материалов данного очень полезного курса?