Операционная система UNIX - страница 114
Рис. 3.19. Мультиплексирование сообщений в одной очереди
Атрибут >msgtype
также можно использовать для изменения порядка извлечения сообщений из очереди. Стандартный порядок получения сообщений аналогичен принципу FIFO — сообщения получаются в порядке их записи. Однако используя тип, например, для назначения приоритета сообщений, этот порядок легко изменить.
Пример приложения "Здравствуй, Мир!", использующего сообщения:
>#define MAXBUFF 80
>#define PERM 0666
>/* Определим структуру нашего сообщения. Она может отличаться
> от структуры msgbuf, но должна содержать поле mtype. В данном
> случае структура сообщения состоит из буфера обмена */
>typedef struct our msgbuf {
> long mtype;
> char buff[MAXBUFF];
>} Message;
>#include
>#include
>#include "mesg.h"
>main() {
> /* Структура нашего сообщения (может отличаться от
> структуры msgbuf) */
> Message message;
> key_t key;
> int msgid, length, n;
> /* Получим ключ */
> if ((key = ftok("server", 'A')) < 0) {
> printf("Невозможно получить ключ\n");
> exit(1);
> }
> /* Тип принимаемых сообщений */
> message.mt_type = 1L;
> /* Создадим очередь сообщений */
> if ((msgid = msgget(key, РЕRМ | IPC_CREAT)) < 0) {
> printf("Невозможно создать очередь\n");
> exit(1);
> }
> /* Прочитаем сообщение */
> n =
> msgrcv(msgid, &message, sizeof(message), message.mtype, 0);
> /* Если сообщение поступило, выведем его содержимое
> на терминал */
> if (n > 0) {
> if (write(1, message.buff, n) != n) {
> printf("Ошибка вывода\n");
> exit(1);
> }
> } else {
> printf("Ошибка чтения сообщения\n");
> exit(1);
> }
> /* Удалить очередь поручим клиенту */
> exit(0);
>}
>#include
>#include
>#include
>#include "mesg.h"
>main {
> /* Структура нашего сообщения (может отличаться от
> структуры msgbuf */
> Message message;
> key_t key;
> int msgid, length;
> /* Тип посылаемого сообщения, может использоваться для
> мультиплексирования */
> message.mtype = 1L;
> /* Получим ключ */
> if ((key = ftok("server", 'A')) < 0) {
> printf("Невозможно получить ключ\n");
> exit(1);
> }
> /* Получим доступ к очереди сообщений, очередь уже
> должна быть создана сервером */
> if ((msgid = msgget(key, 0)) < 0) {
> printf("Невозможно получить доступ к очереди\n");
> exit(1);
> }
> /* Поместим строку в сообщение */
> if ((length = sprintf(message.buff,
> "Здравствуй, Мир!\n")) < 0) {
> printf("Ошибка копирования в буфер\n");
> exit(1);
> } /* Передадим сообщение */
> if (msgsnd(msgid, (void*)&message, length, 0) != 0) {
> printf("Ошибка записи сообщения в очередь\n");
> exit(1);
> }
> /* Удалим очередь сообщений */
> if (msgctl(msgid, IPC_RMID, 0) < 0) {
> printf("Ошибка удаления очереди\n");
> exit(1);
> }
> exit(0);
>}
Семафоры
Для синхронизации процессов, а точнее, для синхронизации доступа нескольких процессов к разделяемым ресурсам, используются семафоры. Являясь одной из форм IPC, семафоры не предназначены для обмена большими объемами данных, как в случае FIFO или очередей сообщений. Вместо этого, они выполняют функцию, полностью соответствующую своему названию — разрешать или запрещать процессу использование того или иного разделяемого ресурса.
Применение семафоров поясним на простом примере. Допустим, имеется некий разделяемый ресурс (например, файл). Необходимо блокировать доступ к ресурсу для других процессов, когда некий процесс производит операцию над ресурсом (например, записывает в файл). Для этого свяжем с данным ресурсом некую целочисленную величину — счетчик, доступный для всех процессов. Примем, что значение 1 счетчика означает доступность ресурса, 0 — его недоступность. Тогда перед началом работы с ресурсом процесс должен проверить значение счетчика. Если оно равно 0 — ресурс занят и операция недопустима — процессу остается ждать. Если значение счетчика равно 1 — можно работать с ресурсом. Для этого, прежде всего, необходимо заблокировать ресурс, т. е. изменить значение счетчика на 0. После выполнения операции для освобождения ресурса значение счетчика необходимо изменить на 1. В приведенном примере счетчик играет роль семафора.
Для нормальной работы необходимо обеспечить выполнение следующих условий: