Проверка режима доступа к файлу происходит немного сложнее, поскольку константы O_RDONLY (0), O_WRONLY (1) и O_RDWR (2) не соответствуют отдельным разрядам флагов состояния открытого файла. По этой причине на значение флагов накладывается маска с помощью константы O_ACCMODE, а затем проводится проверка на равенство одной из констант:

accessMode = flags & O_ACCMODE;

if (accessMode == O_WRONLY || accessMode == O_RDWR)

printf("file is writable\n");

Команду F_SETFL системного вызова fcntl() можно использовать для изменения некоторых флагов состояния открытого файла. К ним относятся O_APPEND, O_NONBLOCK, O_NOATIME, O_ASYNC и O_DIRECT. Попытки изменить другие флаги игнорируются. (В некоторых других реализациях UNIX системному вызову fcntl() разрешается изменять и другие флаги, например O_SYNC.)

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

• Файл был открыт не вызывающей программой, поэтому она не может управлять флагами, использованными в вызове open() (например, файл мог быть представлен одним из стандартных дескрипторов, открытых еще до запуска программы).

• Файловый дескриптор был получен не из open(), а из другого системного вызова. Примерами таких системных вызовов могут служить pipe(), который создает конвейер и возвращает два файловых дескриптора, ссылающихся на оба конца конвейера, и socket(), который создает сокет и возвращает дескриптор файла, ссылающийся на сокет.

Чтобы изменить флаги состояния открытого файла, сначала с помощью вызова fcntl() извлекаются копии существующих флагов, затем изменяются нужные разряды и, наконец, делается еще один вызов fcntl() для обновления флагов. Таким образом, чтобы включить флаг O_APPEND, можно написать следующий код:

int flags;

flags = fcntl(fd, F_GETFL);

if (flags == -1)

errExit("fcntl");

flags |= O_APPEND;

if (fcntl(fd, F_SETFL, flags) == -1)

errExit("fcntl");

5.4. Связь файловых дескрипторов с открытыми файлами

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

Чтобы разобраться в происходящем, нужно изучить три структуры данных, обслуживаемые ядром:

• таблицу дескрипторов файлов для каждого процесса;

• общесистемную таблицу дескрипторов открытых файлов;

• таблицу индексных дескрипторов файловой системы.

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

• набор флагов, управляющих работой файлового дескриптора (такой флаг всего один — флаг закрытия при выполнении — close-on-exec, и он будет рассмотрен в разделе 27.4);

• ссылку на дескриптор открытого файла.

Ядро обслуживает общесистемную таблицу всех дескрипторов открытых файлов. (Она иногда называется таблицей открытых файлов, а записи в ней — дескрипторами открытых файлов.) В дескрипторе открытого файла хранится вся информация, относящаяся к открытому файлу, включая:

• текущее файловое смещение (обновляемое системными вызовами read() и write() или явно изменяемое с помощью системного вызова lseek());

• флаги состояния при открытии файла (то есть аргумент flags системного вызова open());

• режим доступа к файлу (только для чтения, только для записи или для чтения и записи, согласно установкам для системного вызова open());

• установки, относящиеся к вводу-выводу, управляемому сигналами (см. раздел 59.3);

• ссылку на индексный дескриптор для этого файла.

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

• тип файла (например, обычный файл, сокет или FIFO-устройство) и права доступа;

• указатель на список блокировок, удерживаемых на этом файле;

• разные свойства файла, включая его размер и метки времени, связанные с различными типами файловых операций.

Перейти на страницу:

Похожие книги