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

на главную - закладки

Жанры

Основы программирования в Linux
Шрифт:

На третьем шаге процесс

cat
с самого начала заблокирован в фоновом режиме. Когда
echo
делает доступными некоторые данные, команда
cat
читает их и выводит в стандартный вывод. Обратите внимание на то, что она затем завершается, не дожидаясь дополнительных данных. Программа
cat
не блокируется, т.к. канал уже закрылся, когда завершилась вторая команда, поместившая данные в FIFO, поэтому вызовы
read
в программе
cat
вернут 0 байтов, обозначая этим конец файла.

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

Примечание

В отличие от канала, созданного вызовом

pipe
, FIFO существует как именованный файл, но не как открытый файловый дескриптор, и должен быть открыт перед тем, как можно будет из него читать данные или в него записывать их. Открывается и закрывается канал FIFO с помощью функций
open
и
close
, которые вы ранее применяли к файлам, но с дополнительными функциональными возможностями. Вызову
open
передается полное имя FIFO вместо полного имени обычного файла.

Открытие FIFO с помощью open

Основное ограничение при открытии канала FIFO состоит в том, что программа не может открыть FIFO для чтения и записи с режимом

O_RDWR
. Если программа нарушит это ограничение, результат будет непредсказуемым. Это очень разумное ограничение, т.к., обычно канал FIFO применяется для передачи данных в одном направлении, поэтому нет нужды в режиме
O_RDWR
. Процесс стал бы считывать обратно свой вывод, если бы канал был открыт для чтения/записи.

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

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

open_flag
(второй параметр функции
open
) со значением
O_NONBLOCK
. Применение этого режима
open
изменяет способ обработки не только вызова
open
, но и запросов
read
и
write
для возвращаемого файлового дескриптора.

Существует четыре допустимых комбинации значений

O_RDONLY
,
O_WRONLY
и
O_NONBLOCK
флага. Рассмотрим их все по очереди.

open(const char *path, O_RDONLY);

В этом случае вызов

open
блокируется, он не вернет управление программе до тех пор, пока процесс не откроет этот FIFO для записи. Это похоже на первый пример с командой
cat
.

open(const char *path, O_RDONLY | O_NONBLOCK);

Теперь вызов

open
завершится успешно и вернет управление сразу, даже если канал FIFO не был открыт для записи каким-либо процессом.

open(const char *path, O_WRONLY);

В данном случае вызов

open
будет заблокирован до тех пор, пока процесс не откроет тот же канал FIFO для чтения.

open(const char *path, O_WRONLY | O_NONBLOCK);

Этот вариант вызова всегда будет возвращать управление немедленно, но если ни один процесс не открыл этот канал FIFO для чтения,

open
вернет ошибку, -1, и FIFO не будет открыт. Если есть процесс, открывший FIFO для чтения, возвращенный файловый дескриптор может использоваться для записи в канал FIFO.

Примечание

Обратите внимание на асимметрию в использовании

O_NONBLOCK
с
O_RDONLY
и
O_WRONLY
, заключающуюся в том, что неблокирующий вызов
open
для записи завершается аварийно, если ни один процесс не открыл канал для чтения, а неблокирующий вызов
open
для чтения не возвращает ошибку. На поведение вызова
close
флаг
O_NONBLOCK
влияния не оказывает.

Выполните упражнение 13.11.

Упражнение 13.11. Открытие файлов FIFO

Теперь рассмотрим, как можно использовать поведение вызова

open
с флагом, содержащим
O_NONBLOCK
, для синхронизации двух процессов. Вместо применения нескольких программ-примеров вы напишите одну тестовую программу fifo2.c, которая позволит исследовать поведение каналов FIFO при передаче ей разных параметров.

1. Начните с заголовочных файлов, директивы

#define
и проверки правильности количества предоставленных аргументов командной строки:

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/stat.h>

#define FIFO_NAME "/tmp/my_fifo"

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

 int res;

 int open_mode = 0;

 int i;

 if (argc < 2) {

fprintf(stderr, "Usage: %s <some combination of\

O_RDONLY O_WRONLY O_NONBLOCK>\n", *argv);

exit(EXIT_FAILURE);

 }

2. Полагая, что программа передает тестовые данные, вы задаете параметр

open_mode
из следующих аргументов:

 for(i = 1; i <argc; i++) {

if (strncmp(*++argv, "O_RDONLY", 8) == 0) open_mode |= O_RDONLY;

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

Брак по-драконьи

Ардова Алиса
Фантастика:
фэнтези
8.60
рейтинг книги
Брак по-драконьи

Черный рынок

Вайс Александр
6. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Черный рынок

Вперед в прошлое 3

Ратманов Денис
3. Вперёд в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 3

Хозяин Стужи 3

Петров Максим Николаевич
3. Злой Лед
Фантастика:
аниме
фэнтези
попаданцы
7.00
рейтинг книги
Хозяин Стужи 3

Черный Маг Императора 17

Герда Александр
17. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Черный Маг Императора 17

Император Пограничья 1

Астахов Евгений Евгеньевич
1. Император Пограничья
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Император Пограничья 1

Я снова князь. Книга XXIII

Дрейк Сириус
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я снова князь. Книга XXIII

#Бояръ-Аниме. Газлайтер. Том 11

Володин Григорий Григорьевич
11. История Телепата
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 11

Рассвет русского царства

Грехов Тимофей
1. Новая Русь
Документальная литература:
историческая литература
5.00
рейтинг книги
Рассвет русского царства

Последний Паладин. Том 8

Саваровский Роман
8. Путь Паладина
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 8

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая

Я - истребитель

Поселягин Владимир Геннадьевич
1. Я - истребитель
Фантастика:
альтернативная история
8.19
рейтинг книги
Я - истребитель

Здравствуй, Мир!

Француз Михаил
Фантастика:
рпг
попаданцы
6.25
рейтинг книги
Здравствуй, Мир!

Проданная Истинная. Месть по-драконьи

Белова Екатерина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Проданная Истинная. Месть по-драконьи