Чтение онлайн

ЖАНРЫ

Программирование для Linux. Профессиональный подход

Самьюэл Алекс

Шрифт:

Существуют и другие флаги, определяющие режим открытия файла. Все они могут объединяться с помощью операции побитового ИЛИ. Перечислим наиболее распространенные флаги.

■ 

O_TRUNC
— приводит к очистке существующего файла. Данные, записываемые в файл, замещают предыдущее содержимое файла.

■ 

O_APPEND
— приводит к открытию файла в режиме добавления. Данные, записываемые в файл, добавляются в его конец.

■ 

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

Когда в функции

open
задан флаг
O_CREAT
, должен присутствовать третий аргумент, определяющий права доступа к создаваемому файлу. О режиме доступа к файлу и битах режима рассказывалось в разделе 10.3, "Права доступа к файлам".

Программа, представленная в листинге Б.1, создает файл, имя которого задано в командной строке. Функции

open
передается флаг
O_EXCL
, поэтому в случае указания существующего файла возникнет ошибка. Владельцу и группе нового файла предоставляются права чтения и записи, остальным пользователям — только право чтения (если для пользователя, которому принадлежит программа, установлено значение
umask
, права доступа к файлу могут оказаться более жесткими).

Значения
umask

При создании файла с помощью функции

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

Для изменения значения

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

Например, функция

umask(S_IRWXO | S_IWGPF);

и команда

% umask 027

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

Листинг Б.1. (createfile.c) Создание файла

#include <fcntl.h>

#include <stdio.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <unistd.h>

int main(int argc, char* argv[]) {

 /* Путевое имя нового файла */

 char* path = argv[1];

 /* Права доступа к файлу. */

 mode_t mode =

S_IRUSR | S_IWUSR| S_IRGRP | S_IWGRP | S_IROTH;

 /* Создание файла. */

 int fd = open(path, O_WRONLY | O_EXCL | O_CREAT, mode);

 if (fd == -1) {

/* Произошла ошибка. Выводим сообщение и завершаем работу. */

perror("open");

return 1;

 }

 return 0;

}

Результаты работы программы будут такими:

% ./create-file testfile

% ls -l testfile

– rw-rw-r-- 1 samuel users 0 Feb 1 22:47 testfile

% ./create-file testfile

open: File exists

Обратите

внимание на то, что длина файла равна нулю, так как программа не записывала в него никакие данные.

Б.1.2. Закрытие файла

По окончании работы с файлом его следует закрыть с помощью функции

close
. В ряде случаев, например в программе, показанной в листинге Б.1, нет необходимости вызывать данную функцию явно, так как ОС Linux автоматически закрывает все открытые файлы по завершении программы. Естественно, после того как файл был закрыт, обращаться к нему нельзя.

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

Linux ограничивает число файлов, которые могут быть открыты процессом в определенный момент времени. Дескрипторы открытых файлов занимают ресурсы ядра, поэтому желательно вовремя закрывать файлы, чтобы дескрипторы удалялись из системных таблиц. Обычно процессам назначается лимит в 1024 дескриптора. Изменить это значение позволяет системный вызов

setrlimit
(см. раздел 8.5, "Функции getrlimit и setrlimit: лимиты ресурсов").

Б.1.3. Запись данных

Для записи данных в файл предназначена функция

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

В листинге Б.2 показана программа, которая записывает в указанный файл значение текущего времени. Если файл не существует, он создается. Для получения и форматирования значения времени программа использует функции

time
,
localtime
и
asctime
.

Листинг Б.2. (timestamp.c) Запись в файл метки времени

#include <fcntl.h>

#include <stdio.h>

#include <string.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <time.h>

#include <unistd.h>

/* Эта строка возвращает строку, содержащую значение

текущих даты и времени. */

char* get_timestamp {

 time_t now = time(NULL);

 return asctime(localtime(&now));

}

int main(int argc, char* argv[]) {

 /* Файл, в который записывается метка времени. */

 char* filename = argv[1];

 /* Получение метки времени. */

 char* timestamp = get_timestamp;

 /* Открытие файла для записи. Если файл существует, он

открывается в режиме добавления; в противном случае

файл создается. */

 int fd =

open(filename. O_WRONLY | O_CREAT | O_APPEND, 0666);

 /* Вычисление длины строки с меткой времени. */

 size_t length = strlen(timestamp);

 /* Запись метки времени в файл. */

 write(fd, timestamp, length);

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