Чтение онлайн

ЖАНРЫ

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

3 main(int argc, char **argv)

4 {

5 int i, id;

6 struct shmid_ds buff;

7 unsigned char c, *ptr;

8 if (argc != 2)

9 err_quit("usage: shmread <pathname>");

10 id = Shmget(Ftok(argv[1], 0), 0, SVSHM_MODE);

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

12 Shmctl(id, IPC_STAT, &buff);

13 /* проверка значений ptr[0] = 0, ptr[1] = 1 и т. д. */

14 for (i = 0; i < buff.shm_segsz; i++)

15 if ((c = *ptr++) != (i % 256))

16 err_ret("ptr[%d] = %d", i.e);

17 exit(0);

18 }

10-12

Открываем и подключаем сегмент разделяемой памяти. Его размер может быть получен вызовом shmctl с командой IPC_STAT. 13-16 Проверяется последовательность, записанная программой shmwrite.

Примеры

Создадим сегмент разделяемой памяти длиной 1234 байта в системе Solaris 2.6. Для идентификации сегмента используем полное имя нашего исполняемого файла shmget. Это имя будет передано функции ftok. Имя исполняемого файла сервера часто используется в качестве уникального идентификатора для данного приложения:

solaris % shmget shmget 1234

solaris % ipcs –bmo

IPC status from <running system> as of Thu Jan 8 13:17:06 1998

T ID KEY MODE OWNER GROUP NATTCH SEGSZ

Shared Memory:

m 1 0x0000f12a –rw-r--r-- rstevens other1 0 1234

Программу ipcs мы запускаем для того, чтобы убедиться, что сегмент разделяемой памяти действительно был создан и не был удален по завершении программы shmcreate. Количество подключений (хранящееся в поле shm_nattch структуры shmid_ds) равно нулю, как мы и предполагали.

Теперь запустим пpoгрaммy shmwrite, чтобы заполнить содержимое разделяемой памяти последовательностью значений. Затем проверим содержимое сегмента разделяемой памяти программой shmread и удалим этот сегмент:

solaris % shmwrite shmget

solaris % shmread shmget

solaris % shmrmid shmget

solaris % ipes –bmo

IPC status from <running system> as of Thu Jan 8 13:17:06 1998

T ID KEY MODE OWNER GROUP NATTCH SEGSZ

Shared Memory:

Мы используем программу ipcs, чтобы убедиться, что сегмент разделяемой памяти действительно был удален.

ПРИМЕЧАНИЕ

При использовании имени исполняемого файла сервера в качестве аргумента ftok для идентификации какого-либо вида IPC System V обычно передается полное имя этого файла (например, /usr/bin/myserverd), а не часть имени, как сделано у нас (shmget). У нас не возникло проблем в этом примере, потому что все программы запускались из того же каталога, в котором был расположен исполняемый файл сервера. Вы помните, что функция ftok использует номер i-node файла для формирования ключа IPC и ей безразлично, определяется файл своим полным именем или его частью (относительным именем). 

14.7. Ограничения, накладываемые на разделяемую память

На разделяемую память System V накладываются определенные ограничения точно так же, как и на семафоры и очереди сообщений System V (раздел 3.8). В табл. 14.1 приведены значения этих ограничений для разных реализаций. В первом столбце приведены традиционные

для System V имена переменных ядра, в которых хранятся эти ограничения.

Таблица 14.1. Типичные значения ограничений, накладываемых на разделяемую память System V

Имя Описание DUnix 4.0B Solaris 2.6
shmmax Максимальный размер сегмента в байтах 4194304 1048576
shmmnb Минимальный размер сегмента разделяемой памяти в байтах 1 1
shmmni Максимальное количество идентификаторов разделяемой памяти в системе 128 100
shmseg Максимальное количество сегментов, подключенных к процессу 32 6

Пример

Программа в листинге 14.5 определяет значения четырех ограничений, приведенных в табл. 14.1.

Листинг 14.5. Определение системных ограничений на разделяемую память

//svshm/limits.c

1 #include "unpipc.h"

2 #define MAX_NIDS 4096

3 int

4 main(int argc, char **argv)

5 {

6 int i, j, shmid[MAX_NIDS];

7 void *addr[MAX_NIDS];

8 unsigned long size;

9 /* проверка максимального количества открываемых идентификаторов */

10 for (i = 0; i <= MAX_NIDS; i++) {

11 shmid[i] = shmget(IPC_PRIVATE, 1024, SVSHM_MODE | IPC_CREAT);

12 if (shmid[i]== –1) {

13 printf("%d identifiers open at once\n", i);

14 break;

15 }

16 }

17 for (j = 0; j < i; j++)

18 Shmctl(shmid[j], IPC_RMID, NULL);

19 /* определяем максимальное количество подключаемых сегментов */

20 for (i=0;i <= MAX_NIDS; i++) {

21 shmid[i] = Shmget(IPC_PRIVATE, 1024, SVSHM_MODE | IPC_CREAT);

22 addr[i] = shmat(shmid[i], NULL, 0);

23 if (addr[i] == (void *) –1) {

24 printf("%d shared memory segments attached at once\n", i);

25 Shmctl(shmid[i], IPC_RMID, NULL); /* удаляем неудачно подключенный сегмент */

26 break;

27 }

28 }

29 for (j = 0; j < i; j++) {

30 Shmdt(addr[j]);

31 Shmcfl(shmid[j], IPC_RMID, NULL);

32 }

33 /* проверка минимального размера сегмента */

34 for (size = 1; ; size++) {

35 shmid[0] = shmget(IPC_PRIVATE, size, SVSHM_MODE | IPC_CREAT);

Поделиться с друзьями: