![]() |
![]() |
Главная страница Взаимодействие нетривиальных процессов Создание двух каналов 18-19 Создаются два канала: contp1pe[0] и contp1pe[l] используются для синхронизации процессов перед началом передачи, а datapipe[0] и datap1pe[l] используются для передачи самих данных. Вызов fork 20-31 Создается дочерний процесс, вызывающий функцию writer, а родительский процесс в это время вызывает функцию reader. Функция reader вызывается п1 оор раз. Функция start time вызывается непосредственно перед началом цикла, а stop time - сразу после его окончания. Эти функции даны в листинге А.З. Полоса пропускания представляет собой количество байтов, переданных за все проходы цикла, поделенное на время, затраченное на передачу (stop time возвращает количество микросекунд, прошедшее с момент запуска start t1me). Затем дочерний процесс завершается сигналом SIGTERM и программа завершает свою работу. Вторая половина программы приведена в листинге А.2. Она состоит из функций reader и writer. Листинг А.2. Функции reader и writer bencli/bw pipe.cvoid 33 void 34 writer(int contfd. int datafd) 35 { 36 int ntowrite: 37 for ( : ; ) { 38 ReadCcontfd. Sntowrite. sizeof(ntowrite)): 39 wliile (ntowrite > 0) { 40 Write(datafd. buf. xfersize); 41 ntowrite -= xfersize: 42 } 43 } 44 } 45 void 46 reader(int contfd. int datafd. int nbytes) 47 { 48 ssize t n; 49 Write(contfd. Snbytes. sizeof(nbytes)); 50 wliile ((nbytes > 0) && 51 ( (n = Read(datafd. buf. xfersize)) > 0)) { 52 nbytes -= n: 53 } 54 } Функция writer 33-44 Функция writer представляет собой бесконечный цикл, вызываемый дочерним процессом. Он ожидает сообщения родительского процесса о готовности к приему данных, считывая целое число из управляющего канала. Это целое чис- ло определяет количество байтов, которое будет записано в канал данных. При получении этого числа дочерний процесс записывает данные в канал, отправляя их родителю. За один вызов write записывается xfersize байтов. Функция reader 45-54 Эта функция вызывается родительским процессом в цикле. Каждый раз при вызове функции в управляющий канал записывается целое число, указывающее дочернему процессу на необходимость помещения соответствующего количества данных в канал данных. Затем функция вызывает read в цикле до тех пор, пока не будут приняты все данные. Текст функций start time, stop time и touch приведен в листинге А.З. Листинг А.З. Функции startsime, stop time и touch lib/timing.с 1 #include unpipc.h 2 static struct timeval tv start, tv stop; 3 int 4 start time(void) 6 return(gettimeofday(&tv start. NULL)): 8 double 9 stop time(void) 10 { 11 double clockus; 12 if (gettimeofday(&tv stop, NULL) == -1) 13 return(O.O): 14 tv sub(&tv stop, &tv start): 15 clockus = tv stop.tv sec * 1000000.0 + tv stop.tv usec: 16 return(clockus); 17 } 18 int 19 touchCvoid *vptr. int nbytes) 20 { 21 char *cptr: 22 static int pagesize = 0: 23 if (pagesize == 0) { 24 errno = 0: 25 #ifdef SC PAGESIZE 26 if ( (pagesize = sysconf( SC PAGESIZE)) == -1) 27 return(-l): 28 #else 29 pagesize = getpagesizeO: /* BSD */ 30 #endif 31 ) 32 cptr = vptr: 33 while (nbytes > 0) { ПРИМЕЧАНИЕ Обратите внимание, что в программе приходится указывать максимальное количество сообщений в очереди при ее создании. Мы указываем значение 4. Размер канала IPC может влиять на производительность, потому что записывающий процесс может отправить это количество сообщений, прежде чем будет заблокирован в вызове mq send, что приведет к переключению контекста на считывающий процесс. Следовательно, производительность программы зависит от этого магического числа. Изменение его 34 *cptr = 1: 35 cptr += pagesize: 36 nbytes -= pagesize; 37 ) 38 return(O): 39 } Текст функции tv sub приведен в листинге А.4. Она осуществляет вычитание двух структур timeval, сохраняя результат в первой структуре. Листинг А.4. Функция tv sub: вычитание двух структур timeval lib/tv sub.c 1 #include unpipc.h 2 void 3 tv sub(struct timeval *out. struct timeval *in) 4 { 5 if ( (out->tv usec -= in->tv usec) < 0) { /* out -= in */ 6 --out->tv sec; 7 out->tv usec += 1000000; 9 out->tv sec -= in->tv sec; 10 } Ha компьютере Sparc под управлением Solaris 2.6 при выполнении программы пять раз подряд получим следующий результат: Solaris % bw pipe 5 10 65536 bandwidth: 13.722 MB/sec Solaris % bw pipe 5 10 65536 bandwidth: 13.781 MB/sec Solaris % bw pipe 5 10 65536 bandwidth: 13.685 MB/sec Solaris % bw pipe 5 10 65536 bandwidth: 13.665 MB/sec Solaris % bw pipe 5 10 65536 bandwidth: 13.584 MB/sec Каждый раз мы задаем пять циклов, 10 Мбайт за цикл и 65 536 байт за один вызов write или read. Среднее от этих пяти результатов даст величину 13,7 Мбайт в секунду, приведенную в табл. А.2. Измерение полосы пропускания очереди сообщений Posix в листинге А.5 приведена функция mai п программы, измеряющей полосу пропускания очереди сообщений Posix. Листинг А.6 содержит функции reader и writer. Эта программа устроена аналогично предыдущей, измерявшей полосу пропускания канала.
|
© 2000 - 2025 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |