Главная страница Взаимодействие нетривиальных процессов Листинг А. 16 (продолжение) 31 Start time(); 32 for (i = 0; i < nloop; i++) 33 doit(msgid); 34 printfC latency: ,3f usec\n , Stop time() / nloop); 35 KilKchildpid, SIGTERM); 36 MsgctKmsgid, IPC RMID, NULL); 37 exitCO): 38 } Мы создаем одну очередь, по которой сообщения передаются в обоих направлениях. Сообщения с типом 1 передаются от родительского процесса дочернему, а сообщения с типом 2 - в обратную сторону. Четвертый аргумент при вызове msgrcv в функции doit имеет значение 2, что обеспечивает получение сообщений только данного типа. Аналогично в дочернем процессе четвертый аргумент msgrcv имеет значение 1, ПРИМЕЧАНИЕ - В разделах 9,3 и 11,3 мы отмечали, что многие структуры, определенные в ядре, нельзя инициализировать статически, поскольку стандарты Posix,l и Unix 98 гарантируют лишь наличие определенных полей в этих структурах, но не определяют ни их порядок, ни наличие других полей, В этой программе мы инициализируем структуру msgbuf статически, поскольку очереди сообщений System V гарантируют, что эта структура содержит поле типа сообщения long, за которым следуют передаваемые данные. Программа измерения задержки интерфейса дверей Программа измерения задержки для интерфейса дверей дана в листинге А, 17. Дочерний процесс создает дверь и связывает с ней функцию server. Родительский процесс открывает дверь и вызывает door cal 1 в цикле, В качестве аргумента передается 1 байт данных, и ничего не возвращается. Листинг А. 17. Программа измерения задержки интерфейса дверей bench/lat door.c 1 #include unpipc.h 2 void 3 serverCvoid *cookie, char *argp, size t arg size. 4 door desc t *dp. size t n descriptors) 6 char c; 7 Door return(&c. sizeof(char). NULL. 0); 9 int 10 mainCint 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: 1 at door <pathname> <#l[oops> ); 18 nloop = atoi(argv[2]): 19 unlink(argv[l]): 20 Close(Open(argv[l], 0 CREAT OJXCL 0 RDWR. FILE MODE)): 21 Pipe(contpipe); 22 if ( (childpid = ForkO) == 0) { 23 doorfd = Door create(server. NULL. 0): 24 Fattach(doorfd. argv[l]); 25 Write(contpipe[l]. &c. 1): 26 for ( : ; ) /* дочерний процесс = сервер */ 27 pauseO: 28 exit(O): 29 } 30 arg.data ptr = &c: /* родительский процесс = клиент */ 31 arg.data size = sizeof(char); 32 arg.descjDtr = 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(rgv[l], 0 RDWR); 39 Door call(doorfd, &arg);~/* запуск */ 40 Start time(); 41 for (i = 0; i < nloop: i++) 42 Door call(doorfd, &arg); 43 printf( latency: .3f usec\n . Stop time() / nloop); 44 KilKchildpid, SIGTERM); 45 unlink(argv[l]); 46 exit(O); 47 } Профамма измерения времени задержки Sun RPC Для измерения времени задержки Sun RPC мы напишем две программы: клиент и сервер, аналогично измерению полосы пропускания. Мы используем старый файл спецификации RPC, но на этот раз клиент вызывает нулевую процедуру сервера. Вспомните упражнение 16.11: эта процедура не принимает никаких аргументов и ничего не возвращает. Это именно то, что нам нужно, чтобы определить задержку. В листинге А.18 приведен текст клиента. Как и в решении упражнения 16.11, нам нужно воспользоваться с1 nt cal 1 для вызова нулевой процедуры; в заглушке клиента отсутствует необходимая заглушка для этой процедуры. Листинг А. 18. Клиент Sun RPC для измерения задержки bench/lat sunrpc client.c 1 #include unpipc.h 2 #include lat sunrpc.h продолжение Листинг А. 18 (продолжение) 3 int 4 mainCint argc, char **argv) 6 int i, nloop: 7 CLIENT *cl; 8 struct timeval tv: 9 if Cargc !- 4) 10 err quitC usage: lat sunrpc client <hostname> <#loops> <protocol> ): 11 nloop - atoiCargv[2]): 12 cl - Clnt createCargv[l], BW SUNRPC PROG, BW SUNRPC VERS, argv[3]): 13 tv,tv sec - 10: 14 tv,tv usec - 0: 15 Start timeC): 16 for Ci = 0: i < nloop: i++) { 17 if Cclnt callCcl, NULLPROC, xdr void, NULL, 18 xdr void, NULL, tv) !- RPC SUCCESS) 19 err quitC *s , clnt sperrorCcl, argv[l])): 20 } 21 printfC latency: .3f usec\n , StopJimeC) / nloop): 22 exitCO): 23 } Мы компилируем сервер с функцией, приведенной в листинге А.13, но она все равно не вызывается. Поскольку мы используем rpcgen для построения клиента и сервера, нам нужно определить хотя бы одну процедуру сервера, но мы не обязаны ее вызывать. Причина, по которой мы используем rpcgen, загслючается в том, что она автоматически создает функцию main сервера с нулевой процедурой, которая нам нужна, А.5. Синхронизация потоков: программы Для измерения времени, уходящего на синхронизацию при использовании различных средств, мы создаем некоторое количество потоков (от одного до пяти, согласно табл. А.4 и А.5), каждый из которых увеличивает счетчик в разделяемой памяти большое количество раз, используя различные формы синхронизации для получения доступа к счетчику. Взаимные исключения Posix в листинге А.19 приведены глобальные переменные и функция mai п программы, измеряющей быстродействие взаимных исключений Posix. Листинг А. 19. Глобальные переменные и функция main для взаимных исключений Posix bench/incr pxmutexl.с 1 #include unpipc.h 2 #define MAXNTHREADS 100 3 int nloop; 4 struct {
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |