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

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

При записи в программный канал или канал FIFO вызовом wri te данные всегда добавляются к уже имеющимся, а вызов read считывает данные, помещенные в программный канал или FIFO первыми. При вызове функции Iseek для программного канала или FIFO будет возвращена ошибка ESPIPE.

Пример

Переделаем программу, приведенную в листинге 4.1, таким образом, чтобы использовать два канала FIFO вместо двух программных каналов. Функции с1 lent и server останутся прежними; отличия появятся только в функции main, новый текст которой приведен в листинге 4.6.

Листинг 4.6. Функция main приложения клиент-сервер, использующего две очереди

pipe/mainfifo.c

1 #include unpipc.h

2 #define FIFOl /tmp/fifo.l

3 #define FIF02 /tmp/fifo.2

4 void clientCint. int). serverCint. int);

5 int

6 mainCint argc. char **argv)

8 int readfd. writefd:

9 pid t childpid;

10 /* создание двух FIFO, если существуют - OK */

11 if CCmkfifoCFIFOl. FILE MODE) < 0) && Cerrno !- EEXIST))

12 err sysC cant create *s . FIFOl):

13 if CCmkfifoCFIF02. FILE MODE) < 0) && Cerrno != EEXIST)) {

14 unlinkCFIFOl):

15 err sysC cant create *s . FIF02);

16 }

17 if С Cchildpid = ForkO) - 0) { /* child */

18 readfd - OpenCFIFOl, 0 RDONLY, 0);

19 writefd - OpenCFIF02. 0 WRONLY. 0);

20 serverCreadfd. writefd):

21 exitCO):

22 }

23 /* родительский процесс */

24 writefd - OpenCFIFOl. 0 WRONLY. 0):

25 readfd - OpenCFIF02. 0 RDONLY. 0):

26 clientСreadfd, writefd):

27 WaitpidCchildpid. NULL. 0): /* ожидание завершения дочернего процесса */

28 CIoseCreadfd):

29 CloseCwritefd):

30 UnlinkCFIFOl): продолжение ё>-



Листинг 4.6 (продолжение)

31 Unlink(FIF02):

32 exit(O):

33 }

Создание двух FIFO

10-16 В файловой системе в каталоге /tmp создается два канала. Если какой-либо из них уже существует - ничего страшного. Константа FILE MODE определена в нашем заголовке unpi рс. h (листинг В.1) как

fdefine FILE MODE (S IRUSR S IWUSR S IRGRP S IROTH) /* разрешения по умолчанию для вновь создаваемых файлов */

При этом владельцу файла разрешается чтение и запись в него, а группе и прочим пользователям - только чтение. Эти биты разрешений накладываются на маску режима доступа создаваемых файлов (file mode creation mask) процесса. 17-27 Далее происходит вызов fork, дочерний процесс вызывает функцию server (листинг 4.3), а родительский процесс вызывает функцию client (листинг4.2). Перед вызовом этих функций родительский процесс открывает первый канал на запись, а второй на чтение, в то время как дочерний процесс открывает первый канал на чтение, а второй - на запись. Картина аналогична примеру с каналами и иллюстрируется рис. 4.11.

родительский процесс

дочерний процесс


/tmp/fifo.1

FIF01

-> поток данных -> /tmp/fifb.2

FIF02

<- поток данных <- Рис. 4.11. Приложение клиент-сервер, использующее две очереди

Изменения по сравнению с примером, в которым использовались программные каналы, следующие:

ш Для создания и открытия программного канала требуется только один вызов - pipe. Для создания и открытия FIFO требуется вызов mkfifo и последующий вызов open.

Ш Программный канал автоматически исчезает после того, как будет закрыт последним использующим его процессом. Канал FIFO удаляется из файловой системы только после вызова unl i nk.

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



здать такой канал, а другому открыть его, даже если последний не является родственным первому. С программными каналами это неосуществимо.

В программах, некорректно использующих каналы FIFO, могут возникать неочевидные проблемы. Рассмотрим, например, листинг 4.6: если поменять порядок двух вызовов функции open в породившем процессе, программа перестанет работать. Причина в том, что чтение из FIFO блокирует процесс, если канал еще не открыт на запись каким-либо другим процессом. Действительно, если мы меняем порядок вызовов open в породившем процессе, и породивший, и порожденный процессы открывают канал на чтение, притом что на запись он еще не открыт, так что оба процесса блокируются. Такая ситуация называется блокированием, или зависанием (deadlock). Она будет рассмотрена подробно в следующем разделе.

Пример: неродственные клиент и сервер

в листинге 4.6 клиент и сервер все еще являлись родственными процессами. Переделаем этот пример так, чтобы родство между ними отсутствовало. В листинге 4.7 приведен текст программы-сервера. Текст практически идентичен той части программы из листинга 4.6, которая относилась к серверу.

Содержимое заголовка f i fо. h приведено в листинге 4.8. Этот файл определяет имена двух FIFO, которые должны быть известны как клиенту, так и серверу.

В листинге 4.9 приведен текст программы-клиента, которая не слишком отличается от части программы из листинга 4.6, относящейся к клиенту. Обратите внимание, что именно клиент, а не сервер удаляет канал FIFO по завершении работы, потому что последние операции с этим каналом выполняются им.

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

pipe/server niain.c

1 #include fifo.h

2 void serverCint. int):

3 int

4 mainCint argc. char **argv)

6 int readfd. writefd:

7 /* создание двух FIFO. OK. если они существуют */

8 if CCmkfifoCFIFOl. FILE MOOE) < 0) && Cerrno !- EEXIST))

9 err sysC cant create *s . FIFOl):

10 if CCmkfifoCFIF02. FILE MODE) < 0) && Cerrno !- EEXIST)) {

11 unlinkCFIFOl);

12 err sysC cant create *s . FIF02):

13 }

14 readfd = OpenCFIFOl. 0 RDONLY. 0):

15 writefd - OpenCFIF02. 0 WRONLY. 0):

16 serverCreadfd. writefd):

17 exitCO):

18 )



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.
Копирование материалов разрешено исключительно при условии цититирования.