Операционная система UNIX - страница 118

стр.

:

>#include

>#include

>#include


>int shmdt(char *shmaddr);

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

Можно привести примерную схему обмена данными между двумя процессами (клиентом и сервером) с использованием разделяемой памяти. Для синхронизации процессов использована группа из двух семафоров. Первый семафор служит для блокирования доступа к разделяемой памяти, его разрешающий сигнал — 0, а 1 является запрещающим сигналом. Второй семафор служит для сигнализации серверу о том, что клиент начал работу. Необходимость применения второго семафора обусловлена следующими обстоятельствами: начальное состояние семафора, синхронизирующего работу с памятью, является открытым (0), и вызов сервером операции заблокирует обращение к памяти для клиента. Таким образом, сервер должен вызвать операцию >mem_lock только после того, как разделяемую память заблокирует клиент. Назначение второго семафора заключается в уведомлении сервера, что клиент начал работу, заблокировал разделяемую память и начал записывать данные в эту область. Теперь, при вызове сервером операции mem_lock его выполнение будет приостановлено до освобождения памяти клиентом, который делает это после окончания записи строки "Здравствуй, Мир!".

shmem.h:

>#define MAXBUFF 80

>#define PERM 0666


>/* Структура данных в разделяемой памяти */

>typedef struct mem_msg {

> int segment;

> char buff[MAXBUFF];

>} Message;


>/* Ожидание начала выполнения клиента */

>static struct sembuf proc_wait[1] = { 1, -1, 0 };


>/* Уведомление сервера о том, что клиент начал работу */

>static struct sembuf proc_start[1] = {

> 1, 1, 0

>};


>/* Блокирование разделяемой памяти */

>static struct sembuf mem_lock[2] = {

> 0, 0, 0,

> 0, 1, 0

>};


>/* Освобождение ресурса */

>static struct sembuf mem_unlock[1] = {

> 0, -1, 0

>};

Сервер:

>#include

>#include

>#include

>#include

>#include "shmem.h"


>main() {

> Message* msgptr;

> key_t key;

> int shmid, semid;

> /* Получим ключ, Один и тот же ключ можно использовать как

>    для семафора, так и для разделяемой памяти */

> if ((key = ftok("server", 'A')) < 0) {

>  printf("Невозможно получить ключ\n");

>  exit(1);

> }


> /* Создадим область разделяемой памяти */

> if ((shmid = shmget(key, sizeof(Message),

>  PERM | IPC_CREAT)) < 0) {

>  printf("Невозможно создать область\n");

>  exit(1);

> }

> /* Присоединим ее */

> if ((msgptr = (Message*)shmat(shmid, 0, 0)) < 0) {

>  printf("Ошибка присоединения\n");

>  exit(1);

> }

> /* Создадим группу из двух семафоров:

>    Первый семафор - для синхронизации работы

>    с разделяемой памятью. Второй семафор -

>    для синхронизации выполнения процессов */


> if ((semid = semget(key, 2, PERM | IPC_CREAT)) < 0) {

>  printf("Невозможно создать семафор\n");

>  exit(1);

> }


> /* Ждем, пока клиент начнет работу и заблокирует разделяемую память */

> if (semop(semid, &proc_wait[0], 1) < 0) {

>  printf("Невозможно выполнить операции\n");

>  exit(1);

> }

> /* Ждем, пока клиент закончит запись в разделяемую память

>    и освободит ее. После этого заблокируем ее */

> if (semop(semid, &mem_lock[0], 2) < 0) {

>  printf("Невозможно выполнить операцию\n");

>  exit(1);

> }

> /* Выведем сообщение на терминал */

> printf(%s, msgptr->buff);


> /* Освободим разделяемую память */

> if (semop(semid, &mem_unlock[0], 1) < 0 {

>  printf("Невозможно выполнить операцию\n");

>  exit(1);

> }


> /* Отключимся от области */

> if (shmdt(msgptr) < 0) {

>  printf("Ошибка отключения\n");

>  exit(1);

> }

> /* Всю остальную работу по удалению объектов сделает клиент */

> exit(0);

>}

Клиент:

>#include

>#include

>#include

>#include

>#include "shmem.h"


>main() {

> Message *msgptr;

> key_t key;

> int shmid, semid;


> /* Получим ключ. Один и тот же ключ можно использовать как

>    для семафора, так и для разделяемой памяти */

> if ((key = ftok("server", 'A')) < 0) {