Уильям Стивенс - UNIX: взаимодействие процессов
- Название:UNIX: взаимодействие процессов
- Автор:
- Жанр:
- Издательство:Питер
- Год:2003
- Город:Санкт-Петербург
- ISBN:5-318-00534-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: взаимодействие процессов краткое содержание
Книга написана известным экспертом по операционной системе UNIX и посвящена описанию одной из форм межпроцессного взаимодействия, IPC, с использованием которой создается большинство сложных программ. В ней описываются четыре возможности разделения решаемых задач между несколькими процессами или потоками одного процесса: передача сообщений, синхронизация, разделяемая память, удаленный вызов процедур.
Книга содержит большое количество иллюстрирующих примеров и может использоваться как учебник по IPC, и как справочник для опытных программистов.
UNIX: взаимодействие процессов - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
1 #include "unpipc.h"
2 #define FIFO1 "/tmp/fifo.1"
3 #define FIFO2 "/tmp/fifo.2"
//pipe/client_main.c
1 #include "fifo.h"
2 void client(int, int);
3 int
4 main(int argc, char **argv)
5 {
6 int readfd, writefd;
7 writefd = Open(FIFO1, O_WRONLY, 0);
8 readfd = Open(FIFO2, O_RDONLY, 0);
9 client(readfd, writefd);
10 Close(readfd);
11 Close(writefd);
12 Unlink(FIFO1);
13 UnLink(FIFO2);
14 exit(0);
15 }
ПРИМЕЧАНИЕ
Для программных каналов и каналов FIFO ядро ведет подсчет числа открытых дескрипторов, относящихся к ним, поэтому безразлично, кто именно вызовет unlink — клиент или сервер. Хотя эта функция и удаляет файл из файловой системы, она не влияет на открытые в момент ее выполнения дескрипторы. Однако для других форм IPC, таких как очереди сообщений стандарта System V, счетчик отсутствует, и если сервер удалит очередь после записи в нее последнего сообщения, она может быть удалена еще до того, как клиент это сообщение считает.
Для запуска клиента и сервера запустите сервер в фоновом режиме:
% server_fifo &
а затем запустите клиент. Можно было сделать и по-другому: запускать только программу-клиент, которая запускала бы сервер с помощью fork и exec. Клиент мог бы передавать серверу имена FIFO в качестве аргументов командной строки в команде exec, вместо того чтобы обе программы считывали их из заголовка. Но в этом случае сервер являлся бы дочерним процессом и проще было бы обойтись программным каналом.
4.7. Некоторые свойства именованных и неименованных каналов
Некоторые свойства именованных и неименованных каналов, относящиеся к их открытию, а также чтению и записи данных, заслуживают более пристального внимания. Прежде всего можно сделать дескриптор неблокируемым двумя способами.
1. При вызове open указать флаг O_NONBLOCK. Например, первый вызов open в листинге 4.9 мог бы выглядеть так:
writefd = Open(FIFO1, O_WRONLY | O_NONBLOCK, 0);
2. Если дескриптор уже открыт, можно использовать fcntl для включения флага O_NONBLOCK. Этот прием нужно применять для программных каналов, поскольку для них не вызывается функция open и нет возможности указать флаг O_NONBLOCK при ее вызове. Используя fcntl, мы сначала получаем текущий статус файла с помощью F_GETFL, затем добавляем к нему с помощью побитового логического сложения (OR) флаг O_NONBLOCK и записываем новый статус с помощью команды F_SETFL:
int flags;
if ((flags = fcntl(fd, F_GETFL, 0)) < 0) err_sys("F_GETFL error");
flags |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, flags) < 0) err_sys("F_SETFL error");
Будьте аккуратны с программами, которые просто устанавливают требуемый флаг, поскольку при этом сбрасываются все прочие флаги состояния:
/* Неправильное отключение блокировки */
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) err_sys("F_SETFL error");
Таблица 4.1 иллюстрирует действие флага, отключающего блокировку, при открытии очереди и при чтении данных из пустого программного канала или канала FIFO.
Таблица 4.1. Действие флага O_NONBLOCK на именованные и неименованные каналы
Операция | Наличие открытых каналов | Блокировка включена (по умолчанию) | Флаг O_NONBLOCK установлен |
---|---|---|---|
Открытие (open) FIFO только для чтения | FIFO открыт на запись | Возвращается код успешного завершения операции | Возвращается код успешного завершения операции |
Открытие (open) FIFO только для чтения | FIFO не открыт на запись | Процесс блокируется, пока FIFO не будет открыт на запись | Возвращается код успешного завершения операции |
Открытие (open) FIFO только для записи | FIFO открыт на чтение | Возвращает код успешного завершения операции | Возвращает код успешного завершения операции |
Открытие (open) FIFO только для записи | FIFO не открыт на чтение | Блокируется до тех пор, пока FIFO не будет открыт на чтение | Возвращает ошибку с кодом ENXIO |
Чтение (read) из пустого программного канала или FIFO | Программный канал или FIFO открыт на запись | Блокируется до тех пор, пока в программный канал или FIFO не будут помещены данные или они не будут закрыты всеми процессами, которыми они были открыты на запись | Возвращает ошибку с кодом EAGAIN |
Чтение (read) из пустого программного канала или FIFO | Программный канал или FIFO не открыт на запись | read возвращает 0 (конец файла) | read возвращает 0 (конец файла) |
Запись (write) в программный канал или FIFO | Программный канал или FIFO открыт на чтение | (См. в тексте) | (См. в тексте) |
Запись (write) в программный канал или FIFO | Программный канал или FIFO не открыт на чтение | Программному потоку посылается сигнал SIGPIPE | Программному потоку посылается сигнал SIGPIPE |
Запомните несколько дополнительных правил, действующих при чтении и записи данных в программные каналы и FIFO.
■ При попытке считать больше данных, чем в данный момент содержится в программном канале или FIFO, возвращается только имеющийся объем данных. Нужно предусмотреть обработку ситуации, в которой функция read возвращает меньше данных, чем было запрошено.
■ Если количество байтов, направленных на запись функции write, не превышает значения PIPE_BUF (ограничение, устанавливаемое стандартом Posix, о котором более подробно рассказывается в разделе 4.11), то ядро гарантирует атомарность операции записи. Это означает, что если два процесса запишут данные в программный канал или FIFO приблизительно одновременно, то в буфер будут помещены сначала все данные от первого процесса, а затем от второго, либо наоборот. Данные от двух процессов при этом не будут смешиваться. Однако если количество байтов превышает значение PIPEBUF, атомарность операции записи не гарантируется.
ПРИМЕЧАНИЕ
Posix.1 требует, чтобы значение PIPE_BUF равнялось по меньшей мере 512. Характерные значения, встречающиеся на практике, лежат в диапазоне от 1024 (BSD/OS 3.1) до 5120 байт (Solaris 2.6). В разделе 4.11 приведен текст программы, выводящей значение этой константы.
■ Установка флага O_NONBLOCK не влияет на атомарность операции записи в про-грaммный канал или FIFO — она определяется исключительно объемом посылаемых данных в сравнении с величиной PIPE_BUF. Однако если для прогрaммнoгo канала или FIFO отключена блокировка, возвращаемое функцией write значение зависит от количества байтов, отправленных на запись, и наличия свободного места в пpoгрaммнoм канале или FIFO. Если количество байтов не превышает величины PIPE_BUF, то:
□ Если в канале достаточно места для записи требуемого количества данных, они будут переданы все сразу.
□ Если места в пpoгрaммнoм канале или FIFO недостаточно для записи требуемого объема данных, происходит немедленное завершение работы функции с возвратом ошибки EAGAIN. Поскольку установлен флаг O_NONBLOCK, процесс не может быть заблокирован, но в то же время ядро не может принять лишь часть данных, так как при этом невозможно гарантировать атомарность операции записи. Поэтому ядро возвращает ошибку, сообщающую процессу о необходимости попытаться произвести запись еще раз.
Читать дальшеИнтервал:
Закладка: