19 nloop = atoi(argv[1]);
20 msgid = Msgget(IPC_PRIVATE, IPC_CREAT | SVMSG_MODE);
21 if ((childpid = Fork()) == 0) {
22 for(;;) { /* дочерний процесс */
23 if (Msgrcv(msgid, &inbuf, sizeof(inbuf.mtext), 1, 0) != 0)
24 err_quit("msgrcv error");
25 Msgsnd(msgid, &child2p, 0, 0);
26 }
27 exit(0);
28 }
29 /* родительский процесс */
30 doit(msgid);
31 Start_time();
32 for (i = 0; i < nloop; i++)
33 doit(msgid);
34 printf("latency: %.3f usec\n", Stop_time() / nloop);
35 Kill(childpid, SIGTERM);
36 Msgctl(msgid, IPC_RMID, NULL);
37 exit(0);
38 }
Мы создаем одну очередь, по которой сообщения передаются в обоих направлениях. Сообщения с типом 1 передаются от родительского процесса дочернему, а сообщения с типом 2 — в обратную сторону. Четвертый аргумент при вызове msgrcv в функции doit имеет значение 2, что обеспечивает получение сообщений только данного типа. Аналогично в дочернем процессе четвертый аргумент msgrcv имеет значение 1.
ПРИМЕЧАНИЕ
В разделах 9.3 и 11.3 мы отмечали, что многие структуры, определенные в ядре, нельзя инициализировать статически, поскольку стандарты Posix.1 и Unix 98 гарантируют лишь наличие определенных полей в этих структурах, но не определяют ни их порядок, ни наличие других полей. В этой программе мы инициализируем структуру msgbuf статически, поскольку очереди сообщений System V гарантируют, что эта структура содержит поле типа сообщения long, за которым следуют передаваемые данные.
Программа измерения задержки интерфейса дверей
Пpoгрaммa измерения задержки для интерфейса дверей дана в листинге А.17. Дочерний процесс создает дверь и связывает с ней функцию server. Родительский процесс открывает дверь и вызывает door_call в цикле. В качестве аргумента передается 1 байт данных, и ничего не возвращается.
//bench/lat_door.c
1 #include "unpipc.h"
2 void
3 server(void *cookie, char *argp, size_t arg_size,
4 door_desc_t *dp, size_t n_descriptors)
5 {
6 char c;
7 Door_return(&c, sizeof(char), NULL, 0);
8 }
9 int
10 main(int argc, char **argv)
11 {
12 int i, nloop, doorfd, contpipe[2];
13 char c;
14 pid_t childpid;
15 door_arg_t arg;
16 if (argc != 3)
17 err_quit("usage: lat_door
18 nloop = atoi(argv[2]);
19 unlink(argv[1]);
20 Close(Open(argv[1], O_CREAT | O_EXCL | O_RDWR, FILE_MODE));
21 Pipe(contpipe);
22 if ((childpid = Fork()) == 0) {
23 doorfd = Door_create(server, NULL, 0);
24 Fattach(doorfd, argv[1]);
25 Write(contpipe[1], &c, 1);
26 for(;;) /* дочерний процесс = сервер */
27 pause();
28 exit(0);
29 }
30 arg.data_ptr = &c /* родительский процесс = клиент */
31 arg.data_size = sizeof(char);
32 arg.desc_ptr = NULL;
33 arg.desc_num = 0;
34 arg.rbuf = &c
35 arg.rsize = sizeof(char);
36 if (Read(contpipe[0], &c, 1) != 1) /* ждем создания */
37 err_quit("pipe read error");
38 doorfd = Open(argv[1], O_RDWR);