Уильям Стивенс - UNIX: взаимодействие процессов
- Название:UNIX: взаимодействие процессов
- Автор:
- Жанр:
- Издательство:Питер
- Год:2003
- Город:Санкт-Петербург
- ISBN:5-318-00534-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: взаимодействие процессов краткое содержание
Книга написана известным экспертом по операционной системе UNIX и посвящена описанию одной из форм межпроцессного взаимодействия, IPC, с использованием которой создается большинство сложных программ. В ней описываются четыре возможности разделения решаемых задач между несколькими процессами или потоками одного процесса: передача сообщений, синхронизация, разделяемая память, удаленный вызов процедур.
Книга содержит большое количество иллюстрирующих примеров и может использоваться как учебник по IPC, и как справочник для опытных программистов.
UNIX: взаимодействие процессов - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
24 if ((attr.mq_maxmsg != 0 && attr.mq_msgsize ==0) ||
25 (attr.mq_maxmsg == 0 && attr.mq_msgsize != 0))
26 err_quit("must specify both –m maxmsg and –z msgsize");
27 mqd = Mq_open(argv[optind], flags, FILE_MODE,
28 (attr.mq_maxmsg != 0) ? &attr : NULL);
29 Mq_close(mqd);
30 exit(0);
31 }
Параметр командной строки, требующий аргумента, указывается с помощью двоеточия (после параметров m и z в вызове getopt). В момент обработки символа параметр optarg указывает на аргумент.
ПРИМЕЧАНИЕ
Наша обертка Getopt вызывает стандартную библиотечную функцию getopt и завершает выполнение процесса в случае возникновения ошибок в ее работе: при появлении параметра, не указанного в третьем аргументе при вызове функции, или при наличии параметра без необходимого числового аргумента (потребность в нем указывается с помощью двоеточия после буквы параметра в третьем аргументе функции getopt). В любом случае, getopt помещает сообщение об ошибке в стандартный поток сообщений об ошибках и возвращает ошибку, что приводит к завершению работы оберткой Getopt. В двух приведенных ниже примерах ошибка обнаруживается функцией getopt:
solaris % mqcreate –z
mqcreate: option requires an argument – z
solaris % mqcreate –q
mqcreate: illegal option – q
В следующем примере ошибка (не указан необходимый аргумент — имя очереди) обнаруживается самой программой:
solaris % mqcreate
usage: mqcreate [ –e ] [ –m maxmsg –z msgsize ]
Если не указан ни один из двух новых параметров, мы должны передать функции mq_open пустой указатель в качестве последнего аргумента. В противном случае мы передаем указатель на нашу структуру attr.
Запустим теперь новую версию нашей программы в системе Solaris 2.6, указав максимальное количество сообщений 1024 и максимальный размер сообщения 8192 байт:
solaris % mqcreate –e –m 1024 -z 8192 /foobar
solaris % ls –al /tmp/.*foobar
-rw-rw-rw– 1 rstevens other1 8397336 Oct 25 11:29 /tmp/.MQDfoobar
–rw-rw-rw– 1 rstevens other1 0 Oct 25 11:29 /tmp/.MQLfoobar
–rw-r--r-- 1 rstevens other1 0 Oct 25 11:29 /tmp/.MQPfoobar
Размер файла, содержащего данные этой очереди, соответствует максимальному количеству сообщений в очереди и максимальному размеру сообщения (1024×8192 = 8388608), а оставшиеся 8728 байт предусматривают 8 байт информации на каждое сообщение (8×1024) плюс дополнительные 536 байт.
При выполнении той же программы в Digital Unix 4.0B получим:
alpha % mqcreate –m 256 -z 2048 /tmp/bigq
alpha % ls-l/tmp/bigq
-rw-r--r-- 1 rstevens system 537288 Oct 25 15:38 /tmp/bigq
В этой реализации размер очереди соответствует максимальному количеству сообщений и максимальному размеру сообщения (256×2048 = 524288), а оставшиеся 13000 байт дают возможность хранить 48 байт добавочной информации для каждого сообщения (48×256) и еще 712 байт.
5.4. Функции mqsend и mqreceive
Эти две функции предназначены для помещения сообщений в очередь и получения их оттуда. Каждое сообщение имеет свой приоритет, который представляет собой беззнаковое целое, не превышающее MQ_PRIO_MAX. Стандарт Posix требует, чтобы эта величина была не меньше 32.
ПРИМЕЧАНИЕ
В Solaris 2.6 значение MQ_PRIO_MAX равняется именно 32, но в Digital Unix 4.0B этот предел равен уже 256. В листинге 5.7 мы покажем, как получить эти значения.
Функция mq_receive всегда возвращает старейшее в указанной очереди сообщение с максимальным приоритетом, и приоритет может быть получен вместе с содержимым сообщения и его длиной.
ПРИМЕЧАНИЕ
Действие mq_receive отличается от действия msgrcv в System V (раздел 6.4). Сообщения System V имеют поле type, аналогичное по смыслу приоритету, но для функции msgrcv можно указать три различных алгоритма возвращения сообщений: старейшее сообщение в очереди, старейшее сообщение с указанным типом или старейшее сообщение с типом, не превышающим указанного значения.
#include
int mq_send(mqd_t mqdes , const char * ptr , size_t len , unsigned int prio );
/* Возвращает 0 в случае успешного завершения, –1 – в случае возникновения ошибок */
ssize_t mq_receive(mqd_t mqdes , char * ptr , size_t len , unsigned int * priop );
/* Возвращает количество байтов в сообщении в случае успешного завершения. –1 – в случае ошибки */
Первые три аргумента обеих функций аналогичны первым трем аргументам функций write и read соответственно.
ПРИМЕЧАНИЕ
Объявление указателя на буфер как char* кажется ошибкой — тип void* больше соответствовал бы по духу прочим функциям Posix.1.
Значение аргумента len функции mq_receive должно быть по крайней мере не меньше максимального размера сообщения, которое может быть помещено в очередь, то есть значения поля mq_msgsize структуры mq_attr для этой очереди. Если len оказывается меньше этой величины, немедленно возвращается ошибка EMSGSIZE.
ПРИМЕЧАНИЕ
Это означает, что большинству приложений, использующих очереди сообщений Posix, придется вызывать mq_getattr после открытия очереди для определения максимального размера сообщения, а затем выделять память под один или несколько буферов чтения этого размера. Требование, чтобы буфер был больше по размеру, чем максимально возможное сообщение, позволяет функции mq_receive не возвращать уведомление о том, что размер письма превышает объем буфера. Сравните это, например, с флагом MSG_NOERROR и ошибкой E2BIG для очередей сообщений System V (раздел 6.4) и флагом MSG_TRUNC для функции recvmsg, используемой с дейтаграммами UDP (раздел 13.5 [24]).
Аргумент prio устанавливает приоритет сообщения для mq_send, его значение должно быть меньше MQ_PRIO_MAX. Если при вызове mq_receive priop является ненулевым указателем, в нем сохраняется приоритет возвращаемого сообщения. Если приложению не требуется использование различных приоритетов сообщений, можно указывать его равным нулю для mq_send и передавать mq_receive нулевой указатель в качестве последнего аргумента.
ПРИМЕЧАНИЕ
Разрешена передача сообщений нулевой длины. Это тот случай, когда важно не то, о чем говорится в стандарте (Posix.1), а то, о чем в нем не говорится: нигде не запрещена передача сообщений нулевой длины. Функция mq_receive возвращает количество байтов в сообщении (в случае успешного завершения работы) или –1 в случае возникновения ошибок, так что 0 обозначает сообщение нулевой длины.
Очередям сообщений Posix и System V не хватает полезной функции: получатель не может определить отправителя сообщения. Эта информация могла бы пригодиться многим приложениям. К сожалению, большинство механизмов передачи сообщений IPC не позволяют определить отправителя сообщений. В разделе 15.5 мы расскажем, как эта возможность обеспечивается для дверей. В разделе 14.8 [24] описано, как эта возможность обеспечивается в BSD/OS для доменных сокетов Unix. В разделе 15.3.1 [21] описано, как SVR4 передает информацию об отправителе по каналу при передаче по нему дескриптора. В настоящее время методы BSD/OS широко используются, и хотя реализация SVR4 является частью стандарта Unix 98, она требует передачи дескриптора по каналу, что обычно является более дорогостоящей операцией, чем просто передача данных. Мы не можем предоставить отправителю возможность передать информацию о себе (например, эффективный идентификатор пользователя) в самом сообщении, поскольку мы не можем быть уверены, что эта информация окажется истинной. Хотя разрешения доступа к очереди сообщений определяют, имеет ли право отправитель помещать в нее сообщения, это все равно не дает однозначности. Существует возможность создавать одну очередь для каждого отправителя (о которой рассказывается в связи с очередями System V в разделе 6.8), но это плохо подходит для больших приложений. Наконец, если функции для работы с очередями сообщений реализованы как пользовательские функции (как мы показываем в разделе 5.8), а не как часть ядра, мы не можем доверять никакой информации об отправителе, передаваемой с сообщением, так как ее легко подделать.
Читать дальшеИнтервал:
Закладка: