Главная страница Взаимодействие нетривиальных процессов 52 53 54 55 ( (п = MsgrcvCmsqid, buf. xfersize - sizeof(long). О, 0)) > 0)) nbytes -= n + sizeof(long); Программа измерения полосы пропускания дверей Программа измерения полосы пропускания интерфейса дверей сложнее, чем предыдущие, поскольку нам нужно вызвать fork перед созданием двери. Родительский процесс создает дверь и с помощью канала оповещает дочерний процесс о том, что ее можно открывать. Другое изменение загслючается в том, что в отличие от рис. А.7 функция reader не принимает данные. Данные принимаются функцией server, которая является процедурой сервера для данной двери. На рис. А.8 изображена схема программы. родительский процесс дочерний процесс процедура сервера измеряется время работы данной функции main ( ) { Pipe (contpipe); if (Forl< () = = 0) { -- doorfd = Door create (); Fattach (); Write (contpipe [1],); reader ( ): exit (0); server ( ) { if (end of data) Write (contpipe [0],); Door return i reader ( ) Write (contpipe [1],); Read (contpipe [1],); -<- forl< () mam i if(Fork() = = 0) { Read (contpipe [0],) doorfd = Open ( ); writer (); exit (0): } Read (contpipe [0],); while (more to send); Wnte (datapipe [1],) Door call ( ); Рис. A.8. Схема программы измерения полосы пропускания дверей Поскольку двери поддерживаются только в Solaris, мы упростим программу, предполагая наличие двустороннего канала (раздел 4.4). Еще одно изменение вызвано фундаментальным различием между передачей сообщений и вызовом процедуры. В программе, работавшей с очередью сообщений Posix, например, записывающий процесс просто помещал сообщения в оче- редь в цикле, что осуществляется асинхронно, В какой-то момент очередь будет заполнена или записывающий процесс будет просто приостановлен, и тогда считывающий процесс получит сообщения. Если, например, в очередь помещается 8 сообщений и записывающий процесс помещал в нее 8 сообщений каждый раз, когда получал управление, а считывающий процесс считывал 8 сообщений, отправка N сообщений требовала N/4 перегслючения контекста. Интерфейс дверей является синхронным: вызывающий процесс блокируется каждый раз при вызове doorcal 1 и не может возобновиться до тех пор, пока сервер не завершит работу. Передача N сообщений в этом случае требует N/2 переключений контекста. С той же проблемой мы столкнемся при измерении полосы пропускания вызовов RPC. Несмотря на увеличившееся количество переключений контекста, из рис. А. 1 следует, что двери обладают наибольшей полосой пропускания при размере сообщений не более 25 Кбайт. В листинге А.9 приведен текст функции main нашей программы. Функции writer, server и reader приведены в листинге А.10. Листинг А.9. Функция main измерения полосы пропускания интерфейса дверей bench/bw door.c 1 #include unpipc.h 2 void reader(int. int): 3 void writer(int): 4 void server(void *. char *. size t. door desc t *. size t): 5 void *buf: 6 int totalnbytes. xfersize. contpipe[2]: 7 int 8 mainCint argc. char **argv) 10 int i. nloop. doorfd: 11 char c: 12 pid t childpid: 13 ssize t n: 14 if (argc != 5) 15 err quit( usage: bw door <pathname> <#loops> <#mbytes> <#bytes/write> ): 16 nloop = atoi(argv[2]): 17 totalnbytes = atoi(argv[3]) * 1024 * 1024: 18 xfersize = atoi(argv[4]): 19 buf = Valloc(xfersize): 20 TouchCbuf. xfersize): 21 unlink(argv[l]): 22 Close(Open(argv[l], OJREAT OJXCL OJDWR, FILE MODE)): 23 Pipe(contpipe); /* предполагается наличие двустороннего канала SVR4 */ 24 if ( (childpid = ForkO) == 0) { 25 /* дочерний процесс = клиент */ 26 if ( (n = Read(contpipe[0], &c, D) != 1) 27 err quit( child: pipe read returned %й , n); 28 doorfd = Open(argv[l], OJDWR): 29 writer(doorfd): 30 exit(O): 31 } 32 /* родительский процесс = сервер */ 33 doorfd = Door create(server. NULL. 0); 34 FattachCdoorfd. argv[l]): 35 Write(contpipe[l]. &c. 1); /* уведомление о готовности двери */ 36 Start time(): 37 for (i = 0: 1 < nloop: i++) 38 readerCdoorfd. totalnbytes); 39 printfCbandwidth: .3f MB/sec\n . 40 totalnbytes / Stop time() * nloop); 41 kilKchildpid. SIGTERM): 42 unlink(argv[l]); 43 exitCO); 44 } Листинг A.I 0. Функции writer, server, reader для интерфейса дверей bench/bw door.c 45 void 46 writerCint 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]. Sntowrite. 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 argsize. 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); л продолжение
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |