Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Низкоуровневый доступ к файлам.doc
Скачиваний:
2
Добавлен:
20.09.2019
Размер:
156.16 Кб
Скачать

Низкоуровневый доступ к файлам

У каждой выполняющейся программы, называемой процессом, есть ряд связанных с ней дескрипторов файлов. Существуют короткие целые (small integer) числа, которые можно использовать для обращения к открытым файлам и устройствам. Количество дескрипторов зависит от конфигурации системы. Когда программа запускается, у нее обычно уже открыты три подобных дескриптора:

  • 0 — стандартный ввод;

  • 1 — стандартный вывод;

  • 2 — стандартный поток ошибок.

Существует возможность связать с файлами и устройствами другие дескрипторы файлов, используя системный вызов функции open. Дескрипторы файлов, открытые автоматически, уже позволяют вам создавать простые программы с помощью вызова write.

Write

Синтаксическая запись системного вызова write:

#include <unistd.h>

size_t write(int fildes, const void *buf, size_t nbytes);

Системный вызов write предназначен для записи из buf первых nbytes байтов в файл, ассоциированный с дескриптором fildes. Он возвращает количество реально записанных байтов, которое может быть меньше nbytes, если в дескрипторе файла обнаружена ошибка или дескриптор файла, расположенный на более низком уровне драйвера устройства, чувствителен к размеру блока. Если функция возвращает 0, это означает, что ничего не записано; если она возвращает -1, в системном вызове write возникла ошибка, которая описывается в глобальной переменной errno.

Пример с использованием системного вызова write:

#include <unistd.h>

#include <stdlib.h>

int main()

{

if ((write(1, "Here is some data\n", 18)) != 18)

write(2, "A write error has occurred on file descriptor 1\n", 46);

exit(0);

}

Результат выполнения данной программы можно видеть на рис. 1:

Рис. 1 Программа с использованием функции write

Эта программа просто помещает сообщение в стандартный вывод. Когда она завершается, все открытые дескрипторы файлов автоматически закрываются.

Read

#include <unistd.h>

size_t read(int fildes, void *buf, size_t nbytes);

Системный вызов read считывает до nbytes байтов данных из файла, ассоциированного с дескриптором файла fildes, и помещает их в область данных buf. Он возвращает количество действительно прочитанных байтов, которое может быть меньше требуемого количества. Если вызов read возвращает 0, ему нечего считывать или достигнут конца файла. Ошибка при вызове заставляет его вернуть -1.

Данная программа (simple_read) копирует первые 128 байтов стандартного ввода в стандартный вывод (она копирует все вводимые данные, если их меньше 128 байтов):

#include <unistd.h>

#include <stdlib.h>

Int main()

{

char buffer[128];

int nread;

nread = read(0, buffer, 128);

if (nread == -1)

write(2, "A read error has occurred\n", 26);

if ((write(1, buffer, nread)) != nread)

write(2, "A write error has occurred\n", 27);

exit(0);

}

Если выполнить программу, будет следующий результат (рис. 2):

Рис. 2 Программа с использованием функции read

Первое выполнение программы с помощью команды echo формирует некоторый ввод программы, который по каналу передается в вашу программу. Во втором выполнении перенаправляется ввод из файла draft1.txt. В этом случае в стандартном выводе появится первая часть указанного файла (128 байтов).

Open

Для создания дескриптора нового файла применяется системный вызов open.

#include <fcntl.h>

#include <sys/types.h>

#include <sys/stat.h>

int open(const char *path, int oflags);

int open(const char *path, int oflags, mode_t mode);

Для использования вызова open можно не включать заголовочные файлы sys/types.h и sys/stat.h в системах, удовлетворяющих стандартам POSIX, но они могут понадобиться в некоторых системах UNIX.

Вызов open устанавливает путь к файлу или устройству. Если установка прошла успешно, он возвращает дескриптор файла, который может применяться в системных вызовах read, write и др. Дескриптор файла уникален и не используется совместно другими процессами, которые могут в данный момент выполняться. Если файл открыт одновременно в двух программах, они поддерживают отдельные дескрипторы файла. Если они обе пишут в файл, то продолжат запись с того места, где остановились. Их данные не чередуются, но данные одной программы могут быть записаны поверх данных другой. У каждой программы свое представление о том, какая порция файла (каково смещение текущей позиции в файле) прочитана или записана. Существует возможность избежать накладки такого сорта с помощью блокировки файла.

Имя открываемого файла или устройства передается как параметр path. Параметр oflags применяется для указания действий, предпринимаемых при открытии файла.

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

Таблица 1

Режим

Описание

О_RDONLY

Открытие только для чтения

О_WRONLY

Открытие только для записи

O_RDWR

Открытие для чтения и записи

Вызов может также включать в параметр oflags комбинацию (с помощью побитовой операции OR) следующих необязательных режимов:

  • O_APPEND — помещает записываемые данные в конец файла;

  • O_TRUNC — задает нулевую длину файла, отбрасывая существующее содержимое;

  • O_CREAT — при необходимости создает файл с правами доступа, заданными в параметре mode;

  • O_EXCL — применяется с режимом O_CREAT, который гарантирует, что вызывающая программа создаст файл. Если файл уже существует, open завершится неудачно;

  • O_BINARY – файл открыт в двоичном режиме;

  • O_TEXT – файл открыт в текстовом режиме.

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

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

Существует также системный вызов creat, стандартизованный POSIX, но он применяется не часто. Он не только создает файл, но также и открывает его. Такой вызов эквивалентен вызову open с параметром oflags, равным O_CREAT|О_WRONLY|O_TRUNC.

Количество файлов, одновременно открытых в любой выполняющейся программе, ограничено. Предельное значение обычно определяется константой OPEN_MAX в заголовочном файле limits.h и меняется от системы к системе, но стандарт POSIX требует, чтобы оно было не меньше 16.

Это значение само по себе может быть ограничено в соответствии с предельными значениями локальной системы, поскольку программа не сможет всегда иметь возможность держать открытыми такое количество файлов. В ОС Linux это предельное значение можно изменять во время выполнения. Как правило, начальное значение OPEN_MAX равно 256.