Аргумент shmid — это идентификатор разделяемой памяти, возвращенный shmget. Функция shmat возвращает адрес начала области разделяемой памяти в адресном пространстве вызвавшего процесса. Правила, по которым формируется этот адрес, таковы:

■ если аргумент shmaddr представляет собой нулевой указатель, система сама выбирает начальный адрес для вызвавшего процесса. Это рекомендуемый (и обеспечивающий наилучшую совместимость) метод;

■ если shmaddr отличен от нуля, возвращаемый адрес зависит от того, был ли указан флаг SHM_RND (в аргументе flag ):

 □ если флаг SHM_RND не указан, разделяемая память подключается непосредственно с адреса, указанного аргументом shmaddr,

 □ если флаг SHM_RND указан, сегмент разделяемой памяти подключается с адреса, указанного аргументом shmaddr, округленного вниз до кратного константе SHMLBA. Аббревиатура LBA означает lower boundary address — нижний граничный адрес.

По умолчанию сегмент подключается для чтения и записи, если процесс обладает соответствующими разрешениями. В аргументе flag можно указать константу SHM_RDONLY, которая позволит установить доступ только на чтение.

<p>14.4. Функция shmdt</p>

После завершения работы с сегментом разделяемой памяти его следует отключить вызовом shmdt:

#include sys/shm.h

int shmdt(const void *shmaddr);

/* Возвращает 0 в случае успешного завершения, –1 – в случае ошибки */

При завершении работы процесса все сегменты, которые не были отключены им явно, отключаются автоматически.

Обратите внимание, что эта функция не удаляет сегмент разделяемой памяти. Удаление осуществляется функцией shmctl с командой IPC_RMIO.

<p>14.5. Функция shmctl</p>

Функция shmctl позволяет выполнять различные операции с сегментом разделяемой памяти:

#include sys/shm.h

int shmctl(int shmid, int and, struct shmid_ds *buff);

/* Возвращает 0 в случае успешного завершения, –1 в случае ошибки */

Команд (значений аргумента cmd) может быть три:

■ IPC_RMID — удаление сегмента разделяемой памяти с идентификатором shmid из системы;

■ IPC_SET — установка значений полей структуры shmid_ds для сегмента разделяемой памяти равными значениям соответствующих полей структуры, на которую указывает аргумент buff: shm_perm.uid, shm_perm.gid, shm_perm.mode. Значение поля shm_ctime устанавливается равным текущему системному времени;

■ IPC_STAT — возвращает вызывающему процессу (через аргумент buff) текущее значение структуры shmid_ds для указанного сегмента разделяемой памяти.

<p>14.6. Простые программы</p>

В этом разделе приведено несколько примеров простых программ, иллюстрирующих работу с разделяемой памятью System V.

<p>Программа shmget</p>

Программа shmget, текст которой приведен в листинге 14.1,[1] создает сегмент разделяемой памяти, принимая из командной строки полное имя и длину сегмента.

Листинг 14.1. Создание сегмента разделяемой памяти System V указанного размера

//svshm/shmget.c

1  #include "unpipc.h"

2  int

3  main(int argc, char **argv)

4  {

5   int c, id, oflag;

6   char *ptr;

7   size_t length;

8   oflag = SVSHM_MODE | IPC_CREAT;

9   while ((c = Getopt(argc, argv, "e")) != –1) {

10   switch (c) {

11   case 'e':

12    oflag |= IPC_EXCL;

13    break;

14   }

15  }

16  if (optind != argc – 2)

17   err_quit("usage: shmget [ –e ] pathname length");

18  length = atoi(argv[optind + 1]);

19  id = Shmget(Ftok(argv[optind], 0), length, oflag);

20  ptr = Shmat(id, NULL, 0);

21  exit(0);

22 }

19 Вызов shmget создает сегмент разделяемой памяти указанного размера. Полное имя, передаваемое в качестве аргумента командной строки, преобразуется в ключ IPC System V вызовом ftok. Если указан параметр –е, наличие существующего сегмента с тем же именем приведет к возвращению ошибки. Если мы знаем, что сегмент уже существует, в командной строке должна быть указана нулевая длина.

20 Вызов shmat подключает сегмент к адресному пространству процесса. После этого программа завершает работу. Разделяемая память System V обладает поменьшей мере живучестью ядра, поэтому сегмент разделяемой памяти при этом не удаляется.

<p>Программа shmrmid</p>

В листинге 14.2 приведен текст тривиальной программы shmrmid, которая вызывает shmctl с командой IPC_RMID для удаления сегмента разделяемой памяти из системы.

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже