Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [ 21 ] 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

Листинг 4.8. Заголовочный файл fifo.h, используемый и клиентом, и сервером

pipe/fifo.h

1 #include unpipc.h

2 #define FIFOl /tmp/fifo.l

3 #define FIF02 /tmp/fifo.2

Листинг 4.9. Функция main независимого клиента

pipe/client main.c

1 #include fifo.h

2 void clientCint. int);

3 int

4 mainCint argc. char **argv)

6 int readfd. writefd:

7 writefd - OpenCFIFOl. 0 WRONLY. 0);

8 readfd - Open(FIF02. 0 RDONLY. 0):

9 client(readfd. writefd):

10 CloseCreadfd);

11 Close(writefd):

12 Unlink(FIFOl):

13 Unlink(FIF02):

14 exit(O);

15 }

ПРИМЕЧАНИЕ -

Для программных каналов и каналов FIFO ядро ведет подсчет числа открытых дескрипторов, относящихся к ним, поэтому безразлично, кто именно вызовет unlink - клиент или сервер. Хотя эта функция и удаляет файл из файловой системы, она не влияет на открытые в момент ее выполнения дескрипторы. Однако для других форм IPC, таких как очереди сообщений стандарта System V, счетчик отсутствует, и если сервер удалит очередь после записи в нее последнего сообщения, она может быть удалена еще до того, как клиент это сообщение считает.

Для запуска клиента и сервера запустите сервер в фоновом режиме: % server fifo &

а затем запустите клиент. Можно было сделать и по-другому: запускать только программу-клиент, которая запускала бы сервер с помощью fork и exec. Клиент мог бы передавать серверу имена FIFO в качестве аргументов командной строки в команде exec, вместо того чтобы обе программы считывали их из заголовка. Но в этом случае сервер являлся бы дочерним процессом и проще было бы обойтись программным каналом.

4.7. Некоторые свойства именованных и.неименованных каналов

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



4.7. Некоторые свойства именованных и неименованных каналов

1. При вызове open указать флаг 0 NONBLOCK. Например, первый вызов open в листинге 4.9 мог бы выглядеть так:

writefd - OpenCFIFOl. 0 WRONLY OJONBLOCK. 0):

2. Если дескриптор уже открыт, можно использовать fcntl для включения флага 0 NONBLOCK. Этот прием нужно применять для программных каналов, поскольку для них не вызывается функция open и нет возможности указать флаг 0 NONBLOCK при ее вызове. Используя fcntl, мы сначала получаем текущий статус файла с помощью F GETFL, затем добавляем к нему с помощью побитового логического сложения (OR) флаг 0 NONBLOCK и записываем новый статус с помощью команды F SETFL:

int flags:

if С Cflags - fcntlCfd. F GETFL. 0)) < 0)

err sysC F GETFL error ): flags I- 0 NONBL0CK: if CfcntlCfd. F SETFL. flags) < 0)

err sysC F SETFL error );

Будьте аккуратны с программами, которые просто устанавливают требуемый флаг, поскольку при этом сбрасываются все прочие флаги состояния:

/* Неправильное отключение блокировки */ if CfcntlCfd. FJETFL. OJONBLOCK) < 0) err sysC F SETFL error ):

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

Таблица 4.1. Действие флага 0 NONBLOCK на именованные и неименованные каналы

Операция

Наличие открытых каналов

Блокировка

включена

(по умолчанию)

Флаг

O.NONBLOCK установлен

Открытие (open) FIFO только для чтения

Открытие (open) FIFO только для чтения

Открытие (open) FIFO только для записи

Открытие (open) FIFO только для записи

Чтение (read) из пустого программного канала или FIFO

FIFO открыт на запись

FIFO не открыт на запись

FIFO открыт на чтение

FIFO не открыт на чтение

Программный канал или FIFO открыт на запись

Возвращается код успешного завершения операции

Процесс блокируется, пока FIFO не будет открыт на запись Возвращает код успешного завершения операдаи

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

Возвращается код успешного заверше-шения операции Возвращается код успешного завершения операции Возвращает код успешного завершения операции Возвращает ошибку с кодом ENXIO

Возвращает ошибку с кодом EAGAIN



Таблица 4.1 (продолжение)

Операция

Наличие открытых каналов

Блокировка

включена

(по умолчанию)

Флаг

0 NONBLOCK установлен

Чтение (read) из пустого программного канала или FIFO Запись (write) в программный канал или FIFO

Запись (write) в программный канал или FIFO

Программный канал или read возвращает О

FIFO не открыт на (конец файла) запись

Программный канал или (См. в тексте) FIFO открыт на чтение

Программный канал или Программному потоку

FIFO не открыт на посьшается сигнал

чтение SIGPIPE

read возвращает О (конец файла)

(См. в тексте)

Программному потоку посылается сигнал SIGPIPE

Запомните несколько дополнительных правил, действующих при чтении и записи данных в программные каналы и FIFO.

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

Ш Если количество байтов, направленных на запись функции write, не превышает значения PIPE BUF (ограничение, устанавливаемое стандартом Posix, о котором более подробно рассказывается в разделе 4.11), то ядро гарантирует атомарность операции записи. Это означает, что если два процесса запишут данные в программный канал или FIFO приблизительно одновременно, то в буфер будут помещены сначала все данные от первого процесса, а затем от второго, либо наоборот. Данные от двух процессов при этом не будут смешиваться. Однако если количество байтов превышает значение PIPE BUF, атомарность операции записи не гарантируется.

ПРИМЕЧАНИЕ

Posix.l требует, чтобы значение PIPE BUF равнялось по меньшей мере 512. Характерные значения, встречающиеся на практике, лежат в диапазоне от 1024 (BSD/OS 3.1) до 5120 байт (Solaris 2.6). В разделе 4.11 приведен текст программы, выводящей значение этой константы.

Установка флага ONONBLOCK не влияет на атомарность операции записи в программный канал или FIFO - она определяется исключительно объемом посылаемых данных в сравнении с величиной PIPEBUF. Однако если для программного канала или FIFO отключена блокировка, возвращаемое функцией wri te значение зависит от количества байтов, отправленных на запись, и наличия свободного места в программном канале или FIFO. Если количество байтов не превышает величины PIPEBUF, то:

□ Если в канале достаточно места для записи требуемого количества данных, они будут переданы все сразу.

□ Если места в программном канале или FIFO недостаточно для записи требуемого объема данных, происходит немедленное завершение работы функ-



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [ 21 ] 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.