- •Сигналы:
- •Группы и сеансы
- •Управление сигналами
- •Отправление сигнала
- •Взаимодействие между процессами
- •Int pipe(int *fieldes);
- •Int mknod(char *pathname, int mode, int dev);
- •Сообщения
- •Int msgget(key_t key, int msgflag);
- •Int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- •Int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
- •Int semget(key_t key, int nsems, int semflag);
- •Int semop(int semid,
- •0, 1, 0}; /* Затем увеличить значение
- •0,1,0 /*Увеличить значение семафора на 1*/
- •Int shmget(key_t key, int size, int shmflag);
- •Int *shmat( int shmid, char *shmaddr, int shmflag);
- •Int shmdt(char *shmaddr);
- •Int segment;
- •Int shmid, semid;
Int *shmat( int shmid, char *shmaddr, int shmflag);
Вызов shmat() возвращает адрес начала области в адресном пространстве процесса размером size, заданным предшествующем вызовом shmget().
Правила получения этого адреса:
1. Если аргумент shmaddr нулевой, то система самостоятельно выбирает адрес.
2. Если аргумент shmaddr отличен от нуля, значение возвращаемого адреса зависит от наличия флажка SHM_RND в аргументе shmflag:
- Если флажок SHM_RND не установлен, система присоединяет разделяемую память к указанному shmaddr адресу.
- Если флажок SHM_RND установлен, система присоединяет разделяемую память к адресу, полученному округлением в меньшую сторону shmaddr до некоторой определенной величины SHMLBA.
По умолчанию разделяемая память присоединяется с правами на чтение и запись.
Эти права можно изменить, указав флажок SHM_RDONLY в аргументе shmflag.
Т.о., несколько процессов могут отображать область разделяемой памяти в различные участки собственного виртуального адресного пространства, как это показано на рис. 3.20.
Окончив работу с разделяемой памятью, процесс отключает (detach) область вызовом:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
Int shmdt(char *shmaddr);
При работе с разделяемой памятью необходимо синхронизировать выполнение взаимодействующих процессов: когда один из процессов записывает данные в разделяемую память, остальные процессы ожидают завершения операции. Обычно синхронизация обеспечивается с помощью семафоров, назначение и число которых определяется конкретным использованием разделяемой памяти.
Примерная схема обмена данными между двумя процессами (клиентом и сервером) с использованием разделяемой памяти.
Для синхронизации процессов использована группа из двух семафоров.
Первый семафор служит для блокирования доступа к разделяемой памяти:
0- разрешающий сигнал,
1 - запрещающий сигнал.
Второй семафор служит для сигнализации серверу о том, что клиент начал работу.
Необходимость применения второго семафора обусловлена следующими обстоятельствами: начальное состояние семафора, синхронизирующего работу с памятью, является открытым (0), и вызов сервером операции mem_lock заблокирует обращение к памяти для клиента. Таким образом, сервер должен вызвать операцию mem_lock только после того, как разделяемую память заблокирует клиент.
Назначение второго семафора заключается в уведомлении сервера, что клиент начал работу, заблокировал разделяемую память и начал записывать данные в эту область.
Теперь, при вызове сервером операции mem_lock его выполнение будет приостановлено до освобождения памяти клиентом, который делает это после окончания записи строки "Здравствуй, Мир!".
shmem.h:
#define MAXBUFF 80
#define PERM 0666
/*Структура данных в разделяемой памяти*/ typedef struct mem_msg{
Int segment;
char buff[MAXBUFF];
}Message;
. /*0жидание начала выполнения клиента*/
static struct sembuf proc_wait[l] = {
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;