Главная страница Взаимодействие нетривиальных процессов 2. Описывая ткf i fo в разделе 4.6, мы сказали, что для открытия существующего FIFO или создания нового, если его не существует, следует вызвать mkfifo, проверить, не возвращается ли ошибка EEXIST, и вызвать open, если это происходит. Что если изменить логику и вызвать сначала open, а затем mkfifo, если FIFO не существует? 3. Что происходит при вызове рореп в листинге 4.5, если в интерпретаторе возникает ошибка? 4. Удалите вызов open для FIFO сервера в листинге 4.10 и проверьте, приведет ли это к завершению работы сервера после отключения последнего клиента. 5. К листингу 4.10: мы отметили, что при запуске сервера его работа блокируется при вызове первой функции open, пока FIFO не будет открыт на запись первым клиентом. Как можно обойти это таким образом, чтобы обе функции open завершали работу немедленно, а блокирование происходило при первом вызове readline? 6. Что произойдет с клиентом в листинге 4.11, если поменять порядок вызовов open? 7. Почему сигнал отправляется процессу, в котором канал FIFO открыт на запись, после отключения последнего читающего клиента, а не читающему клиенту после отключения последнего пишущего? 8. Напишите небольшую тестирующую программу для определения того, возвращает ли fstat количество байтов в FIFO в качестве поля st si ze структуры stat. 9. Напишите небольшую тестирующую программу для определения того, что возвращает функция select при проверке возможности записи в дескриптор канала, у которого закрыт второй конец. ГЛАВА 5 Очереди сообщений Posix 5.1. Введение Очередь сообщений можно рассматривать как связный список сообщений. Программные потоки с соответствующими разрешениями могут помещать сообщения в очередь, а потоки с другими соответствующими разрешениями могут извлекать их оттуда. Каждое сообщение представляет собой запись (вспомните сравнение потоков и сообщений в разделе 4.10), и каждому сообщению его отправителем присваивается приоритет. Для записи сообщения в очередь не требуется наличия ожидающего его процесса. Это отличает очереди сообщений от программных каналов и FIFO, в которые нельзя произвести запись, пока не появится считывающий данные процесс. Процесс может записать в очередь какие-то сообщения, после чего они могут быть получены другим процессом в любое время, даже если первый завершит свою работу. Мы говорим, что очереди сообщений обладают живучестью ядра (kernel persistence, раздел 1.3). Это также отличает их от программных каналов и FIFO. В главе 4 говорится о том, что данные, остающиеся в именованном или неименованном канале, сбрасываются, после того как все процессы закроют его. В этой главе рассматриваются очереди сообщений стандарта Posix, а в главе 6 - стандарта System V. Функции для работы с ними во многом схожи, а главные отличия заключаются в следующем; Ш операция считывания из очереди сообщений Posix всегда возвращает самое старое сообщение с наивысшим приоритетом, тогда как из очереди System V можно считать сообщение с произвольно указанным приоритетом; ш очереди сообщений Posix позволяют отправить сигнал или запустить программный поток при помещении сообщения в пустую очередь, тогда как для очередей System V ничего подобного не предусматривается. Каждое сообщение в очереди состоит из следующих частей: Ш приоритет (беззнаковое целое, Posix) либо тип сообщения (целое типа long, System V); длина полезной части сообщения, которая может быть нулевой; Ш собственно данные (если длина сообщения отлична от 0). Этим очереди сообщений отличаются от программных каналов и FIFO. Последние две части сообщения представляют собой байтовые потоки, в которых отсутствуют границы между сообщениями и никак не указывается их тип. Мы обсуждали этот вопрос в разделе 4.10 и добавили свой собственный интерфейс для пересылки сообщений по программным каналам и FIFO. На рис. 5.1 показан возможный вид очереди сообщений. head mg maxmsg mg msgsize next priority = 30 iengtli = 1 data next priority = 20 iengtli = 2 data NULL priority = 10 iengtli = 3 data Рис. 5.1. Очередь сообщений Posix, содержащая три сообщения Мы предполагаем реализацию через связный список, причем его заголовок содержит два атрибута очереди: максимально допустимое количество сообщений в ней и максимальный размер сообщения. Об этих атрибутах мы расскажем более подробно в разделе 5.3. В этой главе мы используем метод, к которому будем прибегать и в дальнейшем, рассматривая очереди сообщений, семафоры и разделяемую память. Поскольку все эти объекты IPC обладают по крайней мере живучестью ядра (вспомните раздел 1.3), мы можем писать небольшие программы, использующие эти методы для экспериментирования с ними и получения большей информации о том, как они работают. Например, мы можем написать программу, создающую очередь сообщений Posix, а потом написать другую программу, которая помещает сообщение в такую очередь, а потом еще одну, которая будет считывать сообщения из очереди. Помещая в очередь сообщения с различным приоритетом, мы увидим, в каком порядке они будут возвращаться функцией mq receive. 5.2. Функции mq open, mq close, mq unlink Функция пк1 ореп создает новую очередь сообщений либо открывает существующую: #include <mqueue.li> mqd t niq open(const cliar *пате. int oflag. ... /* mdej. mode, struct niq attr *attr */ ); /* Возвращает дескриптор очереди в случае успешного завершения: -1 - в противном случае. */ Требования к аргументу пате описаны в разделе 2.2. Аргумент oflag может принимать одно из следующих значений: 0 RDONLY, 0 WRONLY, 0 RDWR в сочетании (логическое сложение) с 0 CREAT, 0 EXCL, 0 NONBLOCK. Все эти флаги описаны в разделе 2.3. При создании новой очереди (указан флаг 0 CREAT и очередь сообщений еще не существует) требуется указание аргументов mode и attr. Возможные значения
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |