Skip to content

Latest commit

 

History

History
145 lines (93 loc) · 14.2 KB

README.md

File metadata and controls

145 lines (93 loc) · 14.2 KB

Файлы, часть 1

Набор заголовочных файлов для использования POSIX API работы с файлами:

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

Дескрипторы

Все открытые файлы представлены в ядре файловыми дескрипторами. Файловый дескриптор – это неотрицательное целое число. Когда процесс открывает существующий файл или создает новый, ядро возвращает ему файловый дескриптор. Чтобы выполнить записьв файл или чтение из него, нужно передать функции read или write его файловый дескриптор, полученный в результате вызова функции open или creat. В соответствии с принятыми соглашениями командные оболочки UNIX ассоциируют файловый дескриптор 0 со стандартным устройством ввода процесса, 1 – со стандартным устройством вывода и 2 – со стандартным устройством вывода сообщений об ошибках. Это соглашение используется командными оболочками и большинством приложений, но не является особенностью ядра UNIX. Тем не менее многие приложения не смогли бы работать, если это соглашение было бы нарушено.

Функция Open

#include <fcntl.h>
int open(const char *pathname, int oflag, ... /* mode_t mode*/);

Возвращает дескриптор файла в случае успеха, –1 в случае ошибки. Третий аргумент обозначен многоточием (...), таким способом стандарт ISO C указывает, что количество остальных аргументов и их типы могут варьироваться. В этой функции третий аргумент используется только при создании нового файла. Этот аргумент приведен в прототипе функции как комментарий. Аргумент pathname представляет имя файла, который будет открыт или создан. Эта функция может принимать большое количество параметров, которые определяются аргументом oflag. Значение этого аргумента формируется объединением по ИЛИ (OR) одной или более констант, определяемых в заголовочном файле fcntl.h и перечисленных ниже:

O_RDONLY Файл открывается только на чтение.

O_WRONLY Файл открывается только на запись.

O_RDWR Файл открывается как для чтения, так и для записи.

В большинстве реализаций для сохранениясовместимости с устаревшим программным обеспечением константа O_RDONLY определяется значением 0, O_WRONLY – 1, O_RDWR – 2. Должна быть указана одна и только одна из этих трех констант. Cписок констант, присутствие которых в аргументе oflag необязательно:

O_APPEND Запись производится в конец файла.

O_CREAT Если файл не существует, он будет создан. Этот флаг требует наличия третьего аргумента функции open(mode), который определяет значения битов прав доступа к создаваемому файлу.

O_EXCL Приводит к появлению ошибки, если файл уже существует и задан флаг O_CREAT. При такой комбинации флагов атомарно выполняется проверка существования файла и его создание, если файл не существует.

O_TRUNC Если файл существует и успешно открывается на запись либо на чтение и запись, то его размер усекается до нуля.

O_NOCTTY Если аргумент pathname ссылается на файл терминального устройства, то это устройство не назначается управляющим терминалом вызывающего процесса.

O_NONBLOCK Если аргумент pathname ссылается на именованный канал (FIFO), специальный блочный файл или специальный символьный файл, этот флаг задает неблокирующий режим открытия файла и последующих операций ввода вывода.

O_DSYNC Каждый вызов функции writeожидает завершения физической операции ввода вывода, но не ожидает, пока будут обновлены атрибуты файла, если они не влияют на возможность чтения только что записанных данных.

O_RSYNC Каждый вызов функции readприостанавливается до тех пор, пока не будут закончены ожидающие завершения операции записи в ту же самую часть файла.

O_SYNC Каждый вызов функции writeожидает завершения физической операции ввода вывода, включая операцию обновления атрибутов файла

Функция Сreat

#include <fcntl.h>
int creat(const char *pathname, mode_t mode);

В случае успеха возвращает файловый дескриптор, доступный только для записи, –1 в случае ошибки Эта функция эквивалентна open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);

У функции creatесть один недостаток: файл открывается только на запись. До появления обновленной версии функции open, чтобы создать временный файл, записать в него некоторые данные и потом прочитать их, требовалось вызывать creat, close и затем open. Гораздо удобнее использовать в таких случаях функцию openследующим образом: open(pathname, O_RDWR | O_CREAT | O_TRUNC, mode);

Функция Close

#include <unistd.h>
int close(int filedes);

Возвращает 0 в случае успеха, –1 в случае ошибки. Закрытие файла также приводит к снятию любых блокировок, которые мог ли быть наложены процессом. При завершении процесса все открытые им файлы автоматически закрываются ядром.

Функция Lseek

С любым открытым файлом связано такое понятие, как текущая позиция файла. Как правило, это неотрицательное целое число, которым выражается количеством байт от начала файла. Обычно операции чтения и записи начинают выполняться с текущей позиции файла и увеличивают ее значение на количество байт, которое было прочитано или записано. По умолчанию при открытии файла текущая позиция инициализируется числом 0, если не был установлен флаг O_APPEND. Явное изменение текущей позиции файла выполняется с помощью функции lseek.

#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);

Возвращает новую текущую позицию файла в случае успеха, –1 в случае ошибки

Интерпретация аргумента offsetзависит от значения аргумента whence.

Если аргумент whenceимеет значение SEEK_SET, то offset интерпретируется как смещение от начала файла.

Если аргумент whenceимеет значение SEEK_CUR, то offset интерпретируется как смещение от текущей позиции файла. В этом случае offset может принимать как положительные, так и отрицательные значения.

Если аргумент whence имеет значение SEEK_END, то offset интерпретируется как смещение от конца файла. В этом случае offset может принимать как положительные, так и отрицательные значения.

Поскольку в случае успеха функция lseek возвращает новую текущую позицию файла, можно задать в аргументе offset значение 0, чтобы узнать текущую позицию:

off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);

Можно воспользоваться этим приемом, чтобы определить, имеется ли возможность свободного перемещения текущей позиции файла. Если файловый дескриптор относится к именованному или неименованному каналу или к сокету, функция lseek вернет значение –1 и запишет в переменную errno код ошибки ESPIPE.

Текущая позиция файла может превышать его текущий размер. В этом случае следующая операция записи увеличит размер файла. Это вполне допустимо и может рассматриваться как создание «пустоты» в файле. Байты, которые фактически не были записаны, считываются как нули. «Пустота» в файле не обязательно должна занимать место на диске. В некоторых файловых системах в случае переноса текущей позиции за пределы файла на диске могут быть выделены новые блоки для данных, но это совершенно необязательно.

Функция Read

#include <unistd.h>
ssize_t read(int filedes, void *buf, size_t nbytes);

Возвращает количество прочитанных байт, 0 – если достигнут конец файла, –1 в случае ошибки.

Существует несколько ситуаций, когда количество фактически прочитанных байт меньше, чем было запрошено:

При чтении из обычного файла, когда конец файла встретился до того, как было прочитано требуемое количество байт. Например, если до конца файла осталось 30 байт, а запрошено было 100 байт, то функция read вернет число 30. При следующем вызове она вернет 0 (конец файла).

При чтении с терминального устройства. Обычно за одно обращение читается одна строка

При чтении данных из сети. Промежуточная буферизация в сети может стать причиной того, что будет получено меньшее количество байт, чем было запрошено.

При чтении из именованных или неименованных каналов. Если в канале содержится меньше байт, чем было запрошено, функция read вернет только то, что ей будет доступно.

При чтении c устройства, ориентированного на доступ к отдельным записям. Примером такого устройства является накопитель на магнитной ленте, который может вернуть только одну запись за одно обращение.

При прерывании операции чтения сигналом в тот момент, когда часть данных уже была прочитана.

Операция чтения начинается с текущей позиции файла. В случае успеха текущая позиция будет увеличена на число фактически прочитанных байт.

Функция Write

include <unistd.h>
ssize_t write(int filedes, const void *buf, size_t nbytes);

Возвращает количество записанных байт в случае успеха, –1 в случае ошибки