Вход/Регистрация
Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

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

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 fcnlt(2) флаг
O_APPEND
не может быть сброшен, если он использовался при открытии файла.

9.4.3.4. Неблокирующий ввод/вывод для каналов и FIFO

Ранее для описания способа работы каналов мы использовали сравнение с двумя людьми, моющими и вытирающими тарелки с использованием сушилки; когда сушилка заполняется, останавливается моющий, а когда она пустеет, останавливается вытирающий. Это блокирующее поведение: производитель или потребитель блокируются в вызове

write
или
read
, ожидая либо освобождения канала, либо появления в нем данных.

В действительности человек, ожидающий опустения или заполнения сушилки, не должен просто неподвижно стоять. [101] Вместо этого незанятый супруг мог бы пойти и найти другую работу по кухне (такую, как подметание всех крошек за детьми на полу), пока сушилка снова не будет готова.

На языке Unix/POSIX эта концепция обозначается термином неблокирующий ввод/вывод, т.е. запрошенный ввод/вывод либо завершается, либо возвращает значение ошибки, указывающее на отсутствие данных (для читающего) или отсутствие места (для записывающего). Неблокирующий ввод/вывод применяется к каналам и FIFO, а не к обычным файлам на диске. Он может применяться также и к определенным устройствам, таким как терминалы, и к сетевым соединениям, обе эти темы выходят за рамки данной книги.

101

Ну, мы игнорируем мысль, что два супруга могли бы хотеть поговорить друг с другом и насладиться компанией — Примеч. автора.

С функцией

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
).

Как описано для обычных каналов, вызов

read
для FIFO, который больше не открыт для чтения, возвращает конец файла (возвращаемое значение 0). Флаг
O_NONBLOCK
в данном случае неуместен. Для пустого канала или FIFO (все еще открытых для записи, но не содержащих данных) все становится интереснее:

read(fd, buf, count) и сброшенный O_NONBLOCK

Функция

read
блокируется до тех пор, пока в канал или FIFO не поступят данные.

read(fd, buf, count) и установленный O_NONBLOCK

Функция

read
немедленно возвращает -1 с установленным в
errno EAGAIN
.

В заключение, поведение

write
более сложно. Для обсуждения этого нам нужно сначала представить концепцию атомарной записи. Атомарная запись — это такая запись, при которой все данные записываются целиком, не чередуясь с данными от других записей. POSIX определяет в
<unistd.h>
константу
PIPE_BUF
. Запись в канал или FIFO данных размером менее или равным
PIPE_BUF
байтов либо успешно завершается, либо блокируется в соответствии с подробностями, которые мы скоро приведем. Минимальным значением для
PIPE_BUF
является
_POSIX_PIPE_BUF
, что равняется 512. Само значение
PIPE_BUF
может быть больше; современные системы GLIBC определяют ее размер в 4096, но в любом случае следует использовать эту именованную константу и не ожидать, что
PIPE_BUF
будет иметь то же значение на разных системах.

  • Читать дальше
  • 1
  • ...
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: