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

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

22 printf( fd[l]: st size = 1d\n , (long) info.st si2e):

23 exit(O):

24 }

9. Вызов sel ect возвращает информацию о возможности записи в дескриптор, но вызов write приводит к отправке сигнала SIGPIPE. Это описано в книге [24, с. 153-155]; когда возникает ошибка чтения или записи, select возвращает информацию о том, что дескриптор доступен, а собственно ошибка возвращается уже вызовами read или write. В листинге Г.4 приведен текст соответствующей программы.

Листинг Г.4. Что возвращает select при закрытии другого конца канала?

pipe/test2.c

1 #include unpipc.h

2 int

3 main(int argc. char **argv)

5 int fd[2], n:

6 pid t childpid;

7 fd set wset;

8 Pipe(fd);

9 if ( (childpid - ForkO) - 0) { /* child */

10 printf( child closing pipe read descriptorVn );

11 Close(fd[0]):

12 sleep(6):

13 exit(O);

14 }

15 /* 4parent */

16 Close(fd[0]): /* для двустороннего канала */

17 sleep(3);

18 FD ZERO(&wset):

19 FD SET(fd[l]. &wset);

20 n = select(fd[l] + 1. NULL. &wset. NULL, NULL):

21 printf( select returned d\n . n):

22 if (FD ISSET(fd[l]. &wset)) {

23 printf( fd[l] writable\n );

24 Write(fd[l], hello , 5):

25 }

26 exit(O);

27 }

Глава 5

1. Сначала создайте очередь, не указывая никаких атрибутов, а затем вызовите niq getattr для получения атрибутов по умолчанию. Затем удалите очередь и создайте ее снова, используя значения по умолчанию для всех неуказанных атрибутов.

2. Для второго сообщения сигнал не отправляется, поскольку регистрация снимается после отправки первого сигнала.



3. Для второго сообщения сигнал не отправляется, поскольку в момент отправки этого сообщения очередь не была пуста.

4. Компилятор GNU С в системе Solaris 2.6 (в котором обе константы определены как вызовы sysconf) возвращает ошибки:

testl.с:13: warning: int format, long int arg (arg 2) testl.c:13: warning: int format, long int arg (arg 3)

5. В Solaris 2.6 мы указываем 1 ООО ООО сообщений по 10 байт в каждом. При этом создается файл размером 20 ООО 536 байт, что соответствует результатам, полученным с помощью программы 5.4: 10 байт данных на сообщение, 8 байт дополнительной информации (возможно, указатели), еще 2 байта добавочной информации (возможно, дополнение до кратного 4) и 536 байт добавочных данных на весь файл. Перед вызовом mq open размер программы, выводимый ps, равнялся 1052 Кбайт, а после создания очереди размер вырос до 20 Мбайт. Это заставляет предположить, что очереди сообщений Posix реализованы через отображение файлов в память, и mq open отображает файл в адресное пространство вызвавшего процесса. Аналогичные результаты получаются в Digital Unix 4.0В.

6. Размер аргумента, равный нулю, не вызывает проблем с функциями ANSI С memXXX. В оригинале стандарта 1989 года ХЗ.159-1989 (ISO/IEC 9899:1990) ничего не говорилось по этому поводу (как и в документации), но в Technical Corrigendum Number 1 явно говорится, что указание размера О не вызовет проблем (но аргументы и указатели при этом должны быть правильными). Вообще, за информацией по языку С лучше всего обращаться по адресу http: WW W. lysator. li u. se/с/.

7. Для двустороннего взаимодействия процессов требуется наличие двух очередей сообщений (см. например, листинг А. 15). Если бы мы изменили листинг 4.4 для использования очередей сообщений Posix вместо каналов, мы бы увидели, что родительский процесс считывает то, что сам же и отправил.

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

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

10. Функция main проводит большую часть времени заблокированной в вызове sel ect, ожидая возможности чтения из конца канала. Каждый раз при получении сигнала возврат из обработчика прерывает вызов select, что приводит к возврату ошибки EINTR. Чтобы избежать этой проблемы, функция-обертка Select проверяет возврат данного кода ошибки и снова вызывает select, как показано в листинге Г.5. В книге [24, с. 124] вы можете найти более подробный рассказ о прерывании системных вызовов.



Листинг Г.5. Обертка Select, обрабатывающая возврат EINTR

lib/wrapunix.c 313 int

314Select(int nfds. fd set *readfds, fd set *writefds. fd set *exceptfds.

315 struct timeval *timeout)

316 {

317 int n:

318 again:

319 if ( (n = select(nfds. readfds. writefds, exceptfds. timeout)) < 0) {

320 if (errno == EINTR)

321 goto again;

322 else

323 err sys( select error ):

324 } else if (n == 0 && timeout == NULL)

325 err quit( select returned 0 with no timeout ):

326 return(n): /* возвращаем 0 no тайм-ауту */

327 }

Глава 6

1. Оставшиеся программы должны принимать идентификатор очереди в числовом виде (вместо полного имени). Это изменение можно осуществить путем добавления нового аргумента командной строки или с помощью предположения, что полное имя, состоящее из одних цифр, является не именем файла, а идентификатором очереди. Поскольку большинство имен файлов, передаваемых ftok, являются абсолютными, они заведомо содержат по крайней мере один нецифровой символ (слэш), и это предположение является вполне корректным.

2. Передача сообщений с типом О запрещена, а клиент никогда не может иметь идентификатор 1, поскольку этот идентификатор обычно принадлежит процессу init.

3. При использовании единственной очереди на рис. 6.2 злоумышленник мог повлиять на все прочие процессы-клиенты. Если у каждого клиента есть своя очередь (рис. 6.3), злоумышленник портит только свою.

Глава 7

2. Вероятно, процесс завершит работу, прежде чем потребитель успеет сделать все, что нужно, поскольку вызов exit завершает все выполняющиеся потоки. .

3. В Solaris 2.6 удаление вызова функций типа destroy приводит к утечке памяти, из чего становится ясно, что функции init осуществляют динамическое выделение памяти. В Digital Unix 4.0В такого не наблюдается, что указывает на разницу в реализации. Тем не менее вызывать функции destroy все равно нужно. С точки зрения реализации в Digital Unix 4.0В используется переменная типа attr t как объект, содержащий атрибуты, а в Solaris 2.6 эта переменная представляет собой указатель на динамически создаваемый объект.



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