Открытие, файла: системный вызов ореn()



 

Чтобы получить возможность прочитать что-то из файла или записать что-то в файл, его нужно открыть. Это делает системный вызов оре n (). Этот системный вызов не имеет постоянного списка аргументов (за счет использования механизма va _ arg); в связи с этим существуют две "разновидности" оре n (). Не только в C++ есть перегрузка функций. Если интересно, то о механизме va _ arg можно прочитать на man-странице stdarg (man 3 stdarg) или в книге Б. Кернигана и Д. Ритчи "Язык программирования Си". Ниже приведены адаптированные прототипы системного вызова оре n ().

int open ( const char * filename , int flags , mode _ t mode );

int open (const char * filename, int flags);

Системный вызов open () объявлен в заголовочном файле fcntl . h. Ниже приведен общий адаптированный прототип оре n ().

int open (const char * filename, int flags,...);

Начнем по порядку. Первый аргумент - имя файла в файловой системе в обычной форме: полный путь к файлу (если файл не находится в текущем каталоге) или сокращенное имя (если файл в текущем каталоге).

Второй аргумент - это режим открытия файла, представляющий собой один или несколько флагов открытия, объединенных оператором побитового ИЛИ. Список доступных флагов приведен в Таблице 4 Приложения 1. Наиболее часто используют только первые семь флагов. Если вы хотите, например, открыть файл в режиме чтения и записи, и при этом автоматически создать файл, если такового не существует, то второй аргумент ореn() будет выглядеть примерно так:

O_RDWR|O_CREAT

Константы-флаги открытия объявлены в заголовочном файле bits / fcntl . h, однако не стоит включать этот файл в свои программы, поскольку он уже включен в файл fcntl . h.

Третий аргумент используется в том случае, если оре n () создает новый файл. В этом случae файлу нужно задать права доступа (режим), с которыми он появится в файловой системе. Права доступа задаются перечислением флагов, объединенных побитовым ИЛИ. Вместо флагов можно использовать число (как правило восьмиричное), однако первый способ нагляднее и предпочтительнее. Список флагов приведен в Таблице 1 Приложения 1. Чтобы, например, созданный файл был доступен в режиме "чтение-запись" пользователем и группой и "только чтение" остальными пользователями, - в третьем аргументе оре n () надо указать примерно следующее: S _ IRUSR | S _ IWUSR | S _ IRGRP | S _ IWGRP | S _ IROTH или 0664. Флаги режима доступа реально объявлены в заголовочном файле bits / stat . h, но он не предназначен для включения в пользовательские программы, и вместо него мы должны включать файл sys / stat . h. Тип mode _ t объявлен в заголовочном файле sys / types . h.

Если файл был успешно открыт, ореn() возвращает файловый дескриптор, по которому мы будем обращаться к файлу. Если произошла ошибка, то ореn() возвращает -1.

 

 

Закрытие файла: системный вызов close ()

 

Системный вызов close () закрывает файл. Вообще говоря, по завершении процесса всe открытые файлы (кроме файлов с дескрипторами 0, 1 и 2) автоматически закрываются. Тем не менее, это не освобождает нас от самостоятельного вызова close (), когда файл нужно закрыть. К тому же, если файлы не закрывать самостоятельно, то соответствующие дескрипторы не освобождаются, что может привести к превышению лимита открытых файлов. Простой пример: приложение может быть настроено так, чтобы каждую минуту открывать и перечитывать свой файл конфигурации для проверки обновлений. Если каждый раз файл не будет закрываться, то в моей системе, например, приложение может "накрыться медным тазом" примерно через 17 часов. Автоматически! Кроме того, файловая система Linux поддерживает механизм буферизации. Это означает, что данные, которые якобы записываются, реально записываются на носитель (синхронизируются) только через какое-то время, когда система сочтет это правильным и оптимальным. Это повышает производительность системы и даже продлевает ресурс жестких дисков. Системный вызов close () не форсирует запись данных на диск, однако дает больше гарантий того, что данные останутся в целости и сохранности.

Системный вызов close () объявлен в файле unistd . h. Ниже приведен его адаптированный прототип:

int close ( int fd );

Очевидно, что единственный аргумент - это файловый дескриптор. Возвращаемое значение 0 в случае успеха, и 1 - в случае ошибки. Довольно часто close () вызывают без проверки возвращаемого значения. Это не очень грубая ошибка, но, тем не менее, иногда закрытие файла бывает неудачным (в случае неправильного дескриптора, в случае прерывания функции по сигналу или в «случае ошибки ввода-вывода, например). В любом случае, если программа сообщит пользователю, что файл невозможно закрыть, это хорошо.

Теперь можно написать простенькую программу, использующую системные вызовы ореn() и close (). Мы еще не умеем читать из файлов и писать в файлы, поэтому напишем программу, которая создает файл с именем, переданным в качестве аргумента (argv [1]) и с правами доступа 0600 (чтение и запись для пользователя). Ниже приведен исходный код программы.

/* openclose . c */

# include < fcntl . h > /* open () and O _ XXX flags */

#include <sys/stat.h> /* S_IXXX flags */

#include <sys/types.h> /* mode_t */

#include <unistd.h> /* close() */

#include <stdlib.h>

#include <stdio.h>

int main (int argc, char ** argv)

{

int fd;

mode_t mode = S_IRUSR | S_IWUSR;

int flags = O_WRONLY | O_CREAT | O_EXCL;

if (argc < 2)

{

fprintf (stderr, "openclose: Too few arguments\n”);

fprintf (stderr, "Usage: openclose <filename>\n");

exit (1);

       }

fd = open (argv[1], flags, mode);

if(fd<0)

{

fprintf (stderr, "openclose: Cannot open file '%s'\n", argv[1]);

exit(1);

}

if (close (fd)!=0)

{

fprintf (stderr, "Cannot close file (descriptor=%d)\n", fd);

exit (1);

}

exit (0);

}

Обратите внимание, если запустить программу дважды с одним и тем же аргументом, то на второй раз оре n () выдаст ошибку. В этом виноват флаг O _ EXCL (см. Таблицу 4 Приложения 1), который "дает добро" только на создание еще не существующих файлов. Наглядности ради, флаги открытия и флаги режима мы занесли в отдельные переменные, однако можно было бы сделать так:

fd = open (argv[1], O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);

Или так:

fd = open (argv[1], O_WRONLY | O_CREAT |O_EXCL, 0600);

 


Дата добавления: 2019-03-09; просмотров: 274; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!