fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
while (running) {
}
exit(EXIT_SUCCESS);
}
В отличие от примера с каналами, процессам нет нужды предоставлять метод их собственной синхронизации. Это существенное преимущество сообщений по сравнению с каналами.
Если в очереди сообщений есть место, отправитель может создать очередь, поместить в нее какие-либо данные и завершить выполнение еще до того, как начнет выполняться приемник. Первой следует запускать программу-отправителя msg2. Далее приведен пример вывода:
$ ./msg2
Enter some text: hello
Enter some text: How are you today?
Enter some text: end
$ ./msg1
You wrote: hello
You wrote: How are you today?
You wrote: end
Как это работает
Программа-отправитель создает очередь сообщений с помощью функции msgget
; далее она добавляет сообщения в очередь, применяя функцию msgsnd
. Программа-приемник получает идентификатор очереди сообщений с помощью функции msgget
и получает сообщения до тех пор, пока не будет найден специальный текст end
. Затем программа приводит все в порядок, удаляя очередь сообщений с помощью функции msgctl
.
Приложение для работы с базой данных компакт-дисков
Сейчас подходящий момент для модификации вашего приложения, управляющего базой данных компакт-дисков, с помощью средств IPC, с которыми вы познакомились в этой главе.
Вы могли бы применить множество разных комбинаций трех разновидностей средств IPC, но поскольку информация, которую следует передавать, очень мала по объему, есть смысл реализовать передачу запросов и ответов непосредственно с помощью очередей сообщений.
Если объемы данных, которые вы должны передавать, были бы велики, можно было бы рассмотреть передачу реальных данных в совместно используемой памяти, одновременно применяя семафоры или сообщения для отправки маркера или "опознавательного знака", информирующего другой процесс о наличии данных в совместно используемой памяти.
Интерфейс очереди сообщений устраняет проблему, которая у вас была в
Вам нужно ответить лишь на один важный вопрос: как возвращать ответы клиентам? Простым решением было бы наличие одной очереди для сервера и по одной очереди для каждого клиента. Если одновременно существует много клиентов, такой подход может вызвать проблемы, т.к. потребуется большое количество очередей. Используя в сообщении поле идентификатора сообщения, вы сможете разрешить всем клиентам пользоваться одной очередью и адресовать ответные сообщения конкретным клиентским процессам с помощью включенного в сообщение идентификатора клиентского процесса. Далее каждый клиент может извлекать сообщения, адресованные только ему, оставляя сообщения для других клиентов в очереди.
Для преобразования приложения, работающего с базой данных компакт-дисков, с помощью средств IPC вам придется заменить только файл pipe_imp.c из сопроводительного программного кода к
Пересмотр функций сервера
Сначала нужно обновить серверные функции.
1. Прежде всего, включите необходимые заголовочные файлы, объявите несколько ключей очередей сообщений и структуру для хранения данных сообщения:
#include "cd_data.h"
#include "cliserv.h"
#include
#define SERVER_MQUEUE 1234
#define CLIENT_MQUEUE 4321
struct msg_passed {
long int msg_key; /* Используется для клиентского pid */
message_db_t real message;
};
2. Две глобальные переменные хранят идентификаторы двух очередей, возвращаемые функцией msgget
:
static int serv_qid = -1;
static int cli_qid = -1;
3. Сделайте сервер ответственным за создание обеих очередей сообщений: