Пример. Работа с общей памятью в рамках одного процесса

Разделяемая память.

Client

Server

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include <string.h>

int main(int argc, char **argv)

{ struct {

long mestype;

char mes [100];

} messageto;

struct {

long mestype;

long mes;

} messagefrom;

key_t key;

int mesid;

key = ftok("example",'r');

mesid = msgget (key, 0666 | IPC_CREAT);

while(1)

{

if (msgrcv(mesid, &messagefrom, sizeof(messagefrom), 1, 0) <= 0) continue;

messageto.mestype = messagefrom.mes;

strcpy(messageto.mes, "Message for client");

msgsnd (mesid, &messageto, sizeof(messageto), 0);

}

msgctl (mesid, IPC_RMID, 0);

return 0;

}

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

#include <unistd.h>

#include <stdio.h>

int main(int argc, char **argv)

{

struct {

long mestype; /*описание структуры сообщения*/

long mes;

} messageto;

struct {

long mestype; /*описание структуры сообшения*/

char mes[100];

} messagefrom;

key_t key;

int mesid;

long pid = getpid();

key = ftok("example", 'r');

mesid = msgget(key, 0); /*присоединение к очереди сообщений*/

messageto.mestype = 1;

messageto.mes = pid;

msgsnd (mesid, &messageto, sizeof(messageto), 0); /* отправка */

while (msgrcv (mesid, &messagefrom, sizeof(messagefrom), pid, 0) <= 0);

/*прием сообщения */

printf("%s\n", messagefrom.mes);

return 0;

}

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

Процесс, подключившийся к разделяемой памяти, может затем получить указатель на некоторый адрес в своем виртуальном адресном пространстве, соответствующий данной области разделяемой памяти. После этого он может работать с этой областью памяти аналогично тому, как если бы она была выделена динамически (например, путем обращения к malloc()), однако, как уже говорилось, разделяемая область памяти не уничтожается автоматически даже после того, как процесс, создавший или использовавший ее, перестанет с ней работать.

shmget()

Создание общей памяти.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int shmget (key_t key, int size, int shmemflg)

Аргументы этого вызова: key - ключ для доступа к разделяемой памяти; size задает размер области памяти, к которой процесс желает получить доступ. Если в результате вызова shmget() будет создана новая область разделяемой памяти, то ее размер будет соответствовать значению size. Если же процесс подключается к существующей области разделяемой памяти, то значение size должно быть не более ее размера, иначе вызов вернет –1. Заметим, что если процесс при подключении к существующей области разделяемой памяти указал в аргументе size значение, меньшее ее фактического размера, то впоследствии он сможет получить доступ только к первым size байтам этой области.

Третий параметр определяет флаги, управляющие поведением вызова.

В случае успешного завершения вызов возвращает положительное число – дескриптор области памяти, в случае неудачи - -1.

shmat()

Доступ к разделяемой памяти.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

char *shmat(int shmid, char *shmaddr, int shmflg)

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

В качестве второго аргумента процесс может указать виртуальный адрес в своем адресном пространстве, начиная с которого необходимо подсоединить разделяемую память. Чаще всего, однако, в качестве значения этого аргумента передается 0, что означает, что система сама может выбрать адрес начала разделяемой памяти. Передача конкретного адреса в этом параметре имеет смысл в том случае, если, к примеру, в разделяемую память записываются указатели на нее же (например, в ней хранится связанный список) – в этой ситуации для того, чтобы использование этих указателей имело смысл и было корректным для всех процессов, подключенных к памяти, важно, чтобы во всех процессах адрес начала области разделяемой памяти совпадал.

Третий аргумент представляет собой комбинацию флагов. В качестве значения этого аргумента может быть указан флаг SHM_RDONLY, который указывает на то, что подсоединяемая область будет использоваться только для чтения.

Эта функция возвращает адрес, начиная с которого будет отображаться присоединяемая разделяемая память.

В случае неудачи вызов возвращает -1.

shmdt()

Открепление разделяемой памяти.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int shmdt(char *shmaddr)

Данный вызов позволяет отсоединить разделяемую память, ранее присоединенную посредством вызова shmat()

shmaddr - адрес прикрепленной к процессу памяти, который был получен при вызове shmat()

В случае успешного выполнения функция возвращает 0, в случае неудачи -1

shmctl()

Управление разделяемой памятью.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

Данный вызов используется для получения или изменения процессом управляющих параметров, связанных с областью разделяемой памяти, наложения и снятия блокировки на нее и ее уничтожения. Аргументы вызова — дескриптор области памяти, команда, которую необходимо выполнить, и структура, описывающая управляющие параметры области памяти. Тип shmid_ds описан в заголовочном файле <sys/shm.h>, и представляет собой структуру, в полях которой хранятся права доступа к области памяти, ее размер, число процессов, подсоединенных к ней в данный момент, и статистика обращений к области памяти.

Возможные значения аргумента cmd:

IPC_STAT – скопировать структуру, описывающую управляющие параметры области памяти по адресу, указанному в параметре buf

IPC_SET – заменить структуру, описывающую управляющие параметры области памяти, на структуру, находящуюся по адресу, указанному в параметре buf. Выполнить эту операцию может процесс, у которого эффективный идентификатор пользователя совпадает с владельцем или создателем очереди, либо процесс с правами привилегированного пользователя, при этом процесс может изменить только владельца области памяти и права доступа к ней.

IPC_RMID – удалить очередь. Как уже говорилось, удалить очередь может только процесс, у которого эффективный идентификатор пользователя совпадает с владельцем или создателем очереди, либо процесс с правами привилегированного пользователя.

SHM_LOCK, SHM_UNLOCK – блокировать или разблокировать область памяти. Выполнить эту операцию может только процесс с правами привилегированного пользователя.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int putm(char *);

int waitprocess(void);

int main(int argc, char **argv)

{

key_t key;

int shmid;

char *shmaddr;

key = ftok(“/tmp/ter”,’S’);

shmid = shmget(key, 100, 0666|IPC_CREAT);

shmaddr = shmat(shmid, NULL, 0); /* подключение к памяти */

putm(shmaddr); /* работа с ресурсом */

waitprocess();

shmctl(shmid,IPC_RMID,NULL); /* уничтожение ресурса */

return 0;

}

В данном примере считается, что putm() иwaitprocess()– некие пользовательские функции, определенные в другом месте



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: