UNIX: взаимодействие процессов
Шрифт:
17 totalnbytes = atoi(argv[3]) * 1024 * 1024;
18 xfersize = atoi(argv[4]);
19 buf = Valloc(xfersize);
20 Touch(buf, xfersize);
21 unlink(argv[1]);
22 Close(Open(argv[1], O_CREAT | O_EXCL | O_RDWR, FILE_MODE));
23 Pipe(contpipe); /* предполагается наличие двустороннего канала SVR4 */
24 if ((childpid = Fork) == 0) {
25 /* дочерний процесс = клиент */
26 if ((n = Read(contpipe[0], &c, 1)) != 1)
27 err_quit("child: pipe read returned %d", n);
28 doorfd = Open(argv[1], O_RDWR);
29 writer(doorfd);
30 exit(0);
31 }
32 /*
родительский процесс = сервер */
33 doorfd = Door_create(server, NULL, 0);
34 Fattach(doorfd, argv[1]);
35 Write(contpipe[1], &c, 1); /* уведомление о готовности двери */
36 Start_time;
37 for (i = 0; i < nloop; i++)
38 reader(doorfd, totalnbytes);
39 printf("bandwidth: %.3f MB/sec\n",
40 totalnbytes / Stop_time * nloop);
41 kill(childpid, SIGTERM);
42 unlink(argv[1]);
43 exit(0);
44 }
Листинг A.10. Функции writer, server, reader для интерфейса дверей
//bench/bw_door.c
45 void
46 writer(int doorfd)
47 {
48 int ntowrite;
49 door_arg_t arg;
50 arg.desc_ptr = NULL; /* дескрипторы не передаются */
51 arg.desc_num = 0;
52 arg.rbuf = NULL; /* значения не возвращаются */
53 arg.rsize = 0;
54 for(;;) {
55 Read(contpipe[0], &ntowrite, sizeof(ntowrite));
56 while (ntowrite > 0) {
57 arg.data_ptr = buf;
58 arg.data_size = xfersize;
59 Door_call(doorfd, &arg);
60 ntowrite –= xfersize;
61 }
62 }
63 }
64 static int ntoread, nread;
65 void
66 server(void *cookie, char *argp, size_t arg_size,
67 door_desc_t *dp, size_t n_descriptors)
68 {
69 char c;
70 nread += arg_size;
71 if (nread >= ntoread)
72 Write(contpipe[0], &c, 1); /* запись закончена */
73 Door_return(NULL, 0, NULL, 0);
74 }
75 void
76 reader(int doorfd, int nbytes)
77 {
78 char c;
79 ssize_t n;
80 ntoread = nbytes; /*
глобальные переменные процедуры сервера */
81 nread = 0;
82 Write(contpipe[1], &nbytes, sizeof(nbytes));
83 if ((n = Read(contpipe[1], &c, 1)) != 1)
84 err_quit("reader: pipe read returned %d", n);
85 }
Программа определения полосы пропускания Sun RPC
Поскольку вызовы процедур в Sun RPC являются синхронными, для них действует то же ограничение, что и для дверей (см. выше). В данном случае проще создать две программы (клиент и сервер), поскольку они создаются автоматически программой rpcgen. В листинге А.11 приведен файл спецификации RPC. Мы объявляем единственную процедуру, принимающую скрытые данные переменной длины в качестве входного аргумента и ничего не возвращающую.
В листинге А.12 приведен текст программы-клиента, а в листинге А.13 — процедура сервера. Мы указываем протокол в качестве аргумента командной строки при вызове клиента, что позволяет нам измерить скорость работы обоих протоколов.
Листинг А.11. Спецификация RPC для измерения полосы пропускания RPC
//bench/bw_sunrpc.х
1 %#define DEBUG /* сервер выполняется в приоритетном режиме */
2 struct data_in {
3 opaque data<>; /* скрытые данные переменной длины */
4 };
5 program BW_SUNRPC_PROG {
6 version BW_SUNRPC_VERS {
7 void BW_SUNRPC(data_in) = 1;
8 } = 1;
9 } = 0x31230001;
Листинг A.12. Клиент RPC для измерения полосы пропускания
//bench/bw_sunrpc_client.с
1 #include "unpipc.h"
2 #include "bw_sunrpc.h"
3 void *buf;
4 int totalnbytes, xfersize;
5 int
6 main(int argc, char **argv)
7 {
8 int i, nloop, ntowrite;
9 CLIENT *cl;
10 data_in in;
11 if (argc != 6)
12 err_quit("usage: bw_sunrpc_client <hostname> <#loops>"
13 " <#mbytes> <#bytes/write> <protocol>");
14 nloop = atoi(argv[2]);
15 totalnbytes = atoi(argv[3]) * 1024 * 1024;
16 xfersize = atoi(argv[4]);
17 buf = Valloc(xfersize);
18 Touch(buf, xfersize);
Поделиться с друзьями: