Главная страница Взаимодействие нетривиальных процессов Глава 3 1. Текст программы приведен в листинге Г. 1. Листинг Г.1. Вывод идентификатора и порядкового номера слота svmsg/slotseq.c 1 #inc1ude unpipc.h 2 int 3 mainCint argc, char **argv) 5 int i. msqid; 6 struct msqid ds info; 7 for (i = 0; i < 10; i++) { 8 msqid = Msgget(IPC PRIVATE, SVMSG MODE IPC CREAT); 9 Msgcti(msqid, IPC STAT. &info); 10 printfCmsqid = Xd. seq = 1u\n , msqid, info.msg perm.seq); 11 Msgct!(msqid. IPC RMID, NULL); 12 } 13 exit(O); 14 } 2. Первый вызов msgget задействует первую свободную очередь сообщений, порядковый номер которой имеет значение 20 после двукратного запуска программы из листинга 3.2, и вернет идентификатор 1000. Если предположить, что следующая доступная очередь сообщений никогда ранее не использовалась, ее порядковый номер будет иметь значение О, а возвращаться будет идентификатор 1. 3. Программа приведена в листинге Г.2. Листинг Г.2. Проверка использования маски создания файла функцией msgget svmsg/testumask.c 1 #include unpipc.h 2 int 3 main(int argc, char **argv) 5 Msgget(IPC PRIVATE, 0666 IPC CREAT IPCJXCL); 6 umink( /trap/fifo.l ); 7 Mkfifo( /tmp/fifo.l , 0666); 8 exit(O); Запустив эту программу, мы увидим, что маска создания файла имеет значение 2 (снять бит записи для прочих пользователей) и этот бит оказывается снятым для канала FIFO, но не для очереди сообщений: Solaris X umask 02 Solaris % testumask Solaris % Is -1 /tmp/fifo.l prw-rw-r-- 1 rstevens otherl 0 Mar 25 16:05 /tmp/fifo.l Solaris t ipcs -q IPC status from <running system> as of Wed Mar 25 16:06:03 1998 T ID KEY MODE OWNER GROUP Message Queues: q 200 00000000 --rw-rw-rw- rstevens otherl 4. При использовании ftok имеется вероятность того, что для двух полных имен получится один и тот же ключ. При использовании IPC PRIVATE сервер знает, что он создает новую очередь, но в этом случае ему нужно записать ее идентификатор в какой-либо файл, чтобы клиенты могли его считать. 5. Вот один из способов обнаружения коллизий: Solaris % find / -links 1 -not -type 1 - print xargs -nl ftokl > temp.l Solaris % wc -1 temp.l 109351 temp.l Solaris % sort +0 -1 temp.l nawk { if (lastkey= $1) print lastline, $0 lastline = $0 lastkey = $1 ) > temp.2 Solaris % wc -1 temp.2 82188 temp.2 Программа f i nd игнорирует файлы, на которые имеется несколько ссылок (поскольку у всех ссылок одинаковый номер узла), и символические ссылки (поскольку функция stat возвращает информацию для файла, на который ссылка указывает). Большой процент коллизий (75,2%) вызван тем, что в Solaris 2.x используется только 12 бит номера узла. Поэтому в файловых системах с числом файлов более 4096 количество коллизий может быть велико. Например, файлы с номерами 4096, 8192, 12 288 и 16 384 будут иметь один и тот же ключ IPC (если все они принадлежат одной файловой системе). Мы запустили эту программу в той же файловой системе, но используя функцию ftok из BSD/OS, которая добавляет номер узла к ключу целиком, и получили всего 849 коллизий (менее 1%). Глава 4 1. Если бы дескриптор fd[l] остался открытым в дочернем процессе при завершении родительского, его операция read для этого дескриптора не вернула бы признак конца файла, потому что дескриптор был бы еще открыт в дочернем процессе. Закрытие fd[l] гарантирует, что после завершения родительского процесса все его дескрипторы закрываются и вызов read для fd[l] возвращает 0. 2. Если поменять местами порядок вызовов, другой процесс сможет создать канал FIFO в промежутке между вызовами open и mkfifo, в результате чего последний вернет ошибку. 3. Если выполнить Solaris % mainopen 2>temp.stderr /etc/ntp.conf > /rnyfile Solaris % cat temp.stderr sh: /rnyfile: cannot create мы увидим, что рореп срабатывает успешно, но fgets считывает символ конца файла. Сообщение об ошибке записывается интерпретатором в стандартный поток сообщений об ошибках. 5. Измените первый вызов open, указав флаг отключения блокировки: readfifo - Open(SERV FIFO, 0 RDONLY OJONBLOCK, 0): Возврат из этого вызова произойдет немедленно, как и из следующего вызова open, поскольку канал уже открыт на чтение. Чтобы избежать ошибки при вызове readline, флаг 0 NONBLOCK для дескриптора readfifo следует снять, перед тем как вызывать эту функцию. 6. Если клиент откроет свой канал на чтение перед открытием канала сервера, все зависнет. Единственный способ избежать блокировки заключается в вызове open для этих двух каналов в порядке, показанном в листинге 4.11, или в использовании флага отключения блокировки. 7. Исчезновение пишущего процесса воспринимается считывающим как конец файла. 8. В листинге Г.З приведен текст соответствующей программы. Листинг Г.З. Возвращает ли fstat количество байтов в канале FIFO? pipe/testl.c 1 #include unpipc.h 2 int 3 maindnt argc. char **argv) 5 int fd[2]; 6 char buff[7]: 7 struct stat info: 8 if (argc != 2) 9 err quit( usage: testl <pathname> ): 10 Mkfifo(argv[l]. FILE MODE): 11 fd[0] OpentargvEl], 0 RDONLY 0 NONBLOCK): 12 fd[l] - Open(argv[l], 0 WRONLY 0 NONBLOCK): 13 /* 4check sizes when FIFO is empty */ 14 Fstat(fd[0], &info); 15 printf( fd[0]: st size = ld\n , (long) info.st size): 16 Fstat(fd[l], &info): 17 printf( fd[l]: st size = ld\n . (long) info.st size): 18 Write(fd[l]. buff, sizeof(buff)): 19 Fstat(fd[0]. &info): 20 printf( fd[0]: st size - ld\n . (long) info.st size): 21 Fstat(fd[l], &info):
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |