Таблица 9.4. Флаги O_open()
, creat()
и fcntl()
Категория | Функции | Флаги |
---|---|---|
Доступ к файлу | open() , fcntl() | O_RDONLY , O_RDWR , O_WRONLY |
Создание файла | open() | O_CREAT , O_EXCL , O_NOCTTY , O_TRUNC |
Статус файла | open() , fcntl() | O_APPEND , O_DSYNC , O_NONBLOCK , O_RSYNC , O_SYNC |
Помимо первоначальной установки различных флагов с помощью open()
, вы можете использовать fcntl()
для получения текущих установок, а также их изменения. Это осуществляется с помощью значений cmd
F_GETFL
и F_SETFL
соответственно. Например, вы можете использовать эти команды для изменения установки неблокирующего флага, O_NONBLOCK
, подобным образом:
int fd_flags;
if ((fd_flags = fcntl(fd, F_GETFL)) < 0)
/* обработать ошибку */
if ((fd_flags & O_NONBLOCK) != 0) { /* Установлен неблокирующий флаг */
fd_flags &= ~O_NONBLOCK; /* Сбросить его */
if (fcntl(fd, F_SETFL, fd_flags) != 0) /* Дать ядру новое значение */
/* обработать ошибку */
}
Помимо самих режимов именованная константа O_ACCMODE
является маской, которую вы можете использовать для выделения из возвращаемого значения режимов прав доступа.
fd_flags = fcntl(fd, F_GETFL);
switch (fd_flags & O_ACCESS) {
case O_RDONLY:
/* ...действия только для чтения... */
break;
case O_WRONLY:
/* ...действия только для записи... */
break;
case O_RDWR:
/* ...действия для чтения и записи... */
break;
}
POSIX требует, чтобы O_RDONLY
, O_RDWR
и O_WRONLY
были побитово различными, таким образом, гарантируется, что код, подобный только что показанному, будет работать и является простым способом определения того, как был открыт произвольный дескриптор файла.
Используя F_SETFL
вы можете также изменить эти режимы, хотя по-прежнему применяется проверка прав доступа. Согласно справочной странице GNU/Linux O_APPEND
не может быть сброшен, если он использовался при открытии файла.
9.4.3.4. Неблокирующий ввод/вывод для каналов и FIFO
Ранее для описания способа работы каналов мы использовали сравнение с двумя людьми, моющими и вытирающими тарелки с использованием сушилки; когда сушилка заполняется, останавливается моющий, а когда она пустеет, останавливается вытирающий. Это write()
или read()
, ожидая либо освобождения канала, либо появления в нем данных.
В действительности человек, ожидающий опустения или заполнения сушилки, не должен просто неподвижно стоять.[101] Вместо этого незанятый супруг мог бы пойти и найти другую работу по кухне (такую, как подметание всех крошек за детьми на полу), пока сушилка снова не будет готова.
На языке Unix/POSIX эта концепция обозначается термином
С функцией open()
может использоваться флаг O_NONBLOCK
для указания неблокирующего ввода/вывода, он может быть установлен и сброшен с помощью fcntl()
. Для open()
и read()
неблокирующий ввод/вывод прост.
Открытие FIFO с установленным или сброшенным O_NONBLOCK
демонстрирует следующее поведение:
open("/fifо/file", O_RDONLY, mode)
Блокируется до открытия FIFO для записи.
open("/fifo/file", O_RDONLY | O_NONBLOCK, mode)
Открывает файл, возвращаясь немедленно.
open("/fifo/file", O_WRONLY, mode)
Блокирует до открытия FIFO для чтения.
open("/fifo/file", O_WRONLY | O_NONBLOCK, mode)
Если FIFO был открыт для чтения, открывает FIFO и немедленно возвращается. В противном случае возвращает ошибку (возвращаемое значение -1 и errno
установлен в ENXIO
).