Чтение онлайн

ЖАНРЫ

Основы программирования в Linux
Шрифт:

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <errno.h>

#include <unistd.h>

#include <sys/msg.h>

#define MAX_TEXT 512

struct my_msg_st {

 long int my_msg_type;

 char some_text[MAX_TEXT];

};

int main {

 int running = 1;

 struct my_msg_st some_data;

 int msgid;

 char buffer = [BUFSIZ];

 msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

 if (msgid == -1) {

fprintf(stderr, "msgget failed with error: %d\n", errno);

exit(EXIT_FAILURE);

 }

 while (running) {

printf("Enter some text: ");

fgets(buffer, BUFSIZ, stdin);

some_data.my_msg_type = 1;

strcpy(some_data.some_text, buffer);

if (msgsnd(msgid, (void*)&some_data, MAX_TEXT, 0)) == -1) {

fpintf(stderr, "msgsnd failed\n");

exit(EXIT_FAILURE);

}

if (strncmp(buffer, "end", 3) == 0) {

running = 0;

}

 }

 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, но поскольку информация, которую следует передавать, очень мала по объему, есть смысл реализовать передачу запросов и ответов непосредственно с помощью очередей сообщений.

Если объемы данных, которые вы должны передавать, были бы велики, можно было бы рассмотреть передачу реальных данных в совместно используемой памяти, одновременно применяя семафоры или сообщения для отправки маркера или "опознавательного знака", информирующего другой процесс о наличии данных в совместно используемой памяти.

Интерфейс очереди сообщений устраняет проблему, которая у вас была в главе 11, когда вы нуждались в открытом канале у обоих процессов в момент передачи данных. Применение очередей сообщений позволяет одному процессу поместить сообщения в очередь, даже если этот процесс в данный момент — единственный пользователь очереди.

Вам нужно ответить лишь на один важный вопрос: как возвращать ответы клиентам? Простым решением было бы наличие одной очереди для сервера и по одной очереди для каждого клиента. Если одновременно существует много клиентов, такой подход может вызвать проблемы, т.к. потребуется большое количество очередей. Используя в сообщении поле идентификатора сообщения, вы сможете разрешить всем клиентам пользоваться одной очередью и адресовать ответные сообщения конкретным клиентским процессам с помощью включенного в сообщение идентификатора клиентского процесса. Далее каждый клиент может извлекать сообщения, адресованные только ему, оставляя сообщения для других клиентов в очереди.

Для преобразования приложения, работающего с базой данных компакт-дисков, с помощью средств IPC вам придется заменить только файл pipe_imp.c из сопроводительного программного кода к главе 13. Далее мы рассмотрим важные разделы замещающего файла ipc_imp.c.

Пересмотр функций сервера

Сначала нужно обновить серверные функции.

1. Прежде всего, включите необходимые заголовочные файлы, объявите несколько ключей очередей сообщений и структуру для хранения данных сообщения:

#include "cd_data.h"

#include "cliserv.h"

#include <sys/msg.h>

#define SERVER_MQUEUE 1234

#define CLIENT_MQUEUE 4321

struct msg_passed {

 long int msg_key; /* Используется для клиентского pid */

 message_db_t real message;

};

2. Две глобальные переменные хранят идентификаторы двух очередей, возвращаемые функцией

msgget
:

Поделиться с друзьями: