Операционная система UNIX
Можно привести примерную схему обмена данными между двумя процессами (клиентом и сервером) с использованием разделяемой памяти. Для синхронизации процессов использована группа из двух семафоров. Первый семафор служит для блокирования доступа к разделяемой памяти, его разрешающий сигнал — 0, а 1 является запрещающим сигналом. Второй семафор служит для сигнализации серверу о том, что клиент начал работу. Необходимость применения второго семафора обусловлена следующими обстоятельствами: начальное состояние семафора, синхронизирующего работу с памятью, является открытым (0), и вызов сервером операции заблокирует обращение к памяти для клиента. Таким образом, сервер должен вызвать операцию
только после того, как разделяемую память заблокирует клиент. Назначение второго семафора заключается в уведомлении сервера, что клиент начал работу, заблокировал разделяемую память и начал записывать данные в эту область. Теперь, при вызове сервером операции mem_lock его выполнение будет приостановлено до освобождения памяти клиентом, который делает это после окончания записи строки "Здравствуй, Мир!".mem_lockshmem.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 <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>#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);}