Средства межпроцессного взаимодействия (IPC) в ОС LINUX. Семафоры и разделяемая память. Ненадежные сигналы, страница 5

extern struct sigevent    notification;

/* Принимаем сообщение */

int n;

n = mq_receive( msg_queue_id, buff, BUF_LEN, &prio );

if( n < 0 )

{

printf( "Server: message receive error!!!\n" );

return;

}

printf( "Server: message received, length = %d\n", n );

printf( "Message: %s\n", buff );

printf( "Prio: %d\n", prio );

/* Отправляем клиенту уведомление */

strcpy( buff, "OK" );

buff[2] = '\0';

prio = 31;

if( mq_send( msg_queue_id, buff, strlen(buff), prio ) < 0 )

{

printf( "Server: send message error!!!\n" );

return;

}

/* Восстанавливаем диспозицию */

signal( SIGUSR1, sigusr1_handler );

/* Перерегистрируемся */

if( mq_notify( msg_queue_id, &notification ) < 0 )

{

printf( "Server: set notify mode queue error!!!\n" );

return;

}

}

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

Уведомление устанавливается с помощью функции mq_notify(), о помещенном в очередь сообщении сигнализирует посылка пользовательского сигнала, обработка принятого сообщения и ответ клиенту ведется в обработчике сигнала.

Ответные сообщения от сервера посылаются с наивысшим приоритетом 31.

Листинг. 5.2.1. Программа-клиент. msg_client.c.

/*

* Сообщения Posix

* Программа клиента

*/

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <mqueue.h>

int main( int argc, char *argv[] )

{

mqd_t               msg_queue_id_rd,

msg_queue_id_wr;

struct mq_attr      msg_queue_attr;

int                 max_len;

char*               buff;

uint_t              prio;

if( argc < 3 )

{

printf( "Client: command line args error!!!\n" );

exit(2);

}

// Получаем доступ к очереди //

msg_queue_id_rd = mq_open( argv[1], O_RDONLY );

msg_queue_id_wr = mq_open( argv[1], O_WRONLY );

if( msg_queue_id_rd < 0 || msg_queue_id_wr < 0 )

{

printf( "Client: open queue error!!!\n" );

exit(3);

}

prio = atoi( argv[2] );

if( mq_getattr( msg_queue_id_rd, &msg_queue_attr ) < 0 )

{

printf( "Client: get queue attr error!!!\n" );

exit(4);

}

max_len = msg_queue_attr.mq_msgsize;

buff = (char*)malloc( max_len );

printf( "Client: connect is OK.\n" );

printf( "Message: " );

scanf( "%s", buff );

// Оправка сообщения серверу //

if( mq_send( msg_queue_id_wr, buff, strlen(buff), prio ) < 0 )

{

printf( "Client: send message error!!!\n" );

exit(5);

}

printf( "Client: send message is OK.\n" );

mq_close( msg_queue_id_wr );

// Прием ответа от сервера //

int n=0;

n = mq_receive( msg_queue_id_rd, buff, max_len, &prio );

if( n < 0 )

{

printf( "Client: message receive error!!!\n" );

exit(6);

}

mq_close( msg_queue_id_rd );

buff[n] = '\0';

printf( "Client: message received, length = %d\n", n );

printf( "Message: %s. ", buff );

printf( "Prio: %d\n", prio );

// Освобождаем выделенную память //

free( buff );

return EXIT_SUCCESS;

}

В программе-клиенте реализована отправка сообщения серверу и прием уведомления. При запуске в аргументах командной строки надо указать имя файла-очереди и приоритет сообщения, которое будет отправлено.

Результаты работы программы.

Терминал программы-сервера

Терминал программы-клиента

# ./server

Server: start.

Server: message received, length = 3

Message: hi!

Prio: 4

Server: message received, length = 6

Message: qwerty

Prio: 4

Server: message received, length = 3

Message: yo!

Prio: 10

Server: terminate

#./client server_queue 4

Client: connect is OK.

Message: hi!

Client: send message is OK.

Client: message received, length = 2

Message: OK. Prio: 31

#./client server_queue 4

Client: connect is OK.

Message: qwerty

Client: send message is OK.

Client: message received, length = 2

Message: OK. Prio: 31

#./client server_queue 10

Client: connect is OK.

Message: yo!

Client: send message is OK.

Client: message received, length = 2

Message: OK. Prio: 31