- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Основы программирования в Linux - Нейл Мэтью
Шрифт:
Интервал:
Закладка:
Другое различие между открытием канала 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;
if (strncmp(*argv, "O_WRONLY", 8) == 0) open_mode |= O_WRONLY;
if (strncmp(*argv, "O_NONBLOCK", 10) == 0) open_mode |= O_NONBLOCK;
}
3. Далее проверьте, существует ли канал FIFO, и при необходимости создайте его. Затем FIFO открывается, и пока программа засыпает на короткое время, выполняется результирующий вывод. В заключение FIFO закрывается.
if (access(FIFO_NAME, F_OK) == -1) {
res = mkfifo(FIFO_NAME, 0777);
if (res != 0) {
fprintf(stderr, "Gould not create fifo %sn", FIFO_NAME);
exit(EXIT_FAILURE);
}
}
printf("Process %d opening FIF0n", getpid());
res = open(FIFO_NAME, open_mode);
printf("Process %d result %dn", getpid(), res);
sleep(5);
if (res != -1) (void)close(res);
printf("Process %d finishedn", getpid());
exit(EXIT_SUCCESS);
}
Как это работает
Эта программа позволяет задать в командной строке комбинации значений O_RDONLY, O_WRONLY и O_NONBLOCK, которые вы хотите применить. Делается это сравнением известных строк с параметрами командной строки и установкой (с помощью |=) соответствующего флага при совпадении строки. В программе используется функция access, проверяющая, существует ли уже файл FIFO, и создающая его при необходимости.
Никогда не уничтожайте FIFO, т.к. у вас нет способа узнать, не использует ли FIFO другая программа.
O_RDONLY и O_WRONLY без O_NONBLOCKТеперь у вас есть тестовая программа, и вы можете проверить комбинации пар. Обратите внимание на то, что первая программа, считыватель, помещена в фоновый режим.
$ ./fifo2 O_RDONLY &
[1] 152
Process 152 opening FIFO
$ ./fifo2 O_WRONLY
Process 153 opening FIFO
Process 152 result 3
Process 153 result 3
Process 152 finished
Process 153 finished
Это, наверное, самое распространенное применение именованных каналов. Оно позволяет читающему процессу стартовать и ждать в вызове open, а затем разрешает обеим программам продолжить выполнение, когда вторая программа откроет канал FIFO. Обратите внимание на то, что и читающий, и пишущий процессы были синхронизированы вызовом open.
ПримечаниеКогда процесс в ОС Linux заблокирован, он не потребляет ресурсы ЦП, поэтому этот метод синхронизации очень эффективен с точки зрения использования ЦП.
O_RDONLY с O_NONBLOCK и O_WRONLYВ следующем примере читающий процесс выполняет вызов open и немедленно продолжается, даже если нет ни одного пишущего процесса. Пишущий процесс тоже немедленно продолжает выполняться после вызова open, потому что канал FIFO уже открыт для чтения.
$ ./fifо2 O_RDONLY O_NONBLOCK &
[1] 160
Process 160 opening fifo
$ ./fifo2 O_WRONLY
Process 161 opening FIFO
Process 160 result 3
Process 161 result 3
Process 160 finished
Process 161 finished
[1]+ Done ./fifo2 O_RDONLY O_NONBLOCK
Эти два примера — вероятно, самые распространенные комбинации режимов open. Не стесняйтесь использовать программу-пример для экспериментов с другими возможными комбинациями.
Чтение из каналов FIFO и запись в нихПрименение режима O_NONBLOCK влияет на поведение вызовов read и write в каналах FIFO.
Вызов read, применяемый для чтения из пустого блокирующего FIFO (открытого без флага O_NONBLOCK), будет ждать до тех пор, пока не появятся данные, которые можно прочесть. Вызов read, применяемый в неблокирующем FIFO, напротив, при отсутствии данных вернет 0 байтов.
Вызов write для записи в полностью блокирующий канал FIFO будет ждать до тех пор, пока данные не смогут быть записаны. Вызов write, применяемый к FIFO, который не может принять все байты, предназначенные для записи, либо:
□ будет аварийно завершен, если был запрос на запись PIPE_BUF байтов или меньше и данные не могут быть записаны;
□ запишет часть данных, если был запрос на запись более чем PIPE_BUF байтов, и вернет количество реально записанных байтов, которое может быть и 0.
Размер FIFO — очень важная характеристика. Существует накладываемый системой предел объема данных, которые могут быть в FIFO в любой момент времени. Он задается директивой #define PIPE_BUF, обычно находящейся в файле limits.h. В ОС Linux и многих других UNIX-подобных системах он обычно равен 4096 байт, но в некоторых системах может быть и 512 байт. Система гарантирует, что операции записи PIPE_BUF или меньшего количества байтов в канал FIFO, который был открыт O_WRONLY (т.е. блокирующий), запишут или все байты, или ни одного.
Несмотря на то, что этот предел не слишком важен в простом случае с одним записывающим каналом FIFO и одним читающим FIFO, очень распространено использование одного канала FIFO, позволяющего разным программам отправлять запросы к этому единственному каналу FIFO. Если несколько разных программ попытаются писать в FIFO в одно и то же время, жизненно важно, чтобы блоки данных из разных программ не перемежались друг с другом, т. е. каждая операция write должна быть "атомарной". Как это сделать?
Если вы ручаетесь, что все ваши запросы write адресованы блокирующему каналу FIFO и их размер меньше PIPE_BUF байтов, система гарантирует, что данные никогда не будут разделены. Вообще это неплохая идея — ограничить объем данных, передаваемых через FIFO блоком в PIPE_BUF байтов, если вы не используете единственный пишущий и единственный читающий процессы.
Выполните упражнение 13.12.
Упражнение 13.12. Связь процессов с помощью каналов FIFOДля того чтобы увидеть, как несвязанные процессы могут общаться с помощью именованных каналов, вам понадобятся две отдельные программы fifo3.c и fifo4.c.

