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

ЖАНРЫ

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

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

Шрифт:

4 {

5 int i, fd;

6 struct stat stat;

7 unsigned char *ptr;

8 if (argc != 2)

9 err_quit("usage: shmwrite <name>");

10 /* open, определяем размер, отображаем в память */

11 fd = Shm_open(argv[1], O_RDWR, FILE_MODE);

12 Fstat(fd, &stat);

13 ptr = Mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE,

14 MAP_SHARED, fd, 0);

15 Close(fd);

16 /*
присваиваем: ptr[0] = 0, ptr[1] = 1 и т. д. */

17 for (i = 0; i < stat.st_size; i++)

18 *ptr++ = i % 256;

19 exit(0);

20 }

10-15 Объект разделяемой памяти открывается вызовом shm_open. Его размер мы узнаем с помощью fstat. Затем файл отображается в память вызовом mmap, после чего его дескриптор может быть закрыт.

16-18 Последовательность записывается в разделяемую память.

Программа shmread

Программа shmread (листинг 13.4) проверяет значения, помещенные в разделяемую память программой shmwrite.

Листинг 13.4. Проверка значений в разделяемой памяти

//pxshm/shmread.c

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5 int i, fd;

6 struct stat stat;

7 unsigned char c, *ptr;

8 if (argc != 2)

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

10 /* вызываем open, узнаем размер, отображаем в память*/

11 fd = Shm_open(argv[1], O_RDONLY, FILE_MODE);

12 Fstat(fd, &stat);

13 ptr = Mmap(NULL, stat.st_size, PROT_READ,

14 MAP_SHARED, fd, 0);

15 Close(fd);

16 /* проверяем равенства ptr[0] = 0, ptr[1] = 1 и т. д. */

17 for (i = 0; i < stat.st_size; i++)

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

19 err_ret("ptr[%d] = %d", i, c);

20 exit(0);

21 }

10-15 Объект разделяемой памяти открывается только для чтения, его размер получается вызовом fstat, после чего он отображается в память с доступом только на чтение, а дескриптор закрывается.

16-19 Проверяются значения, помещенные в разделяемую память вызовом shmwrite.

Примеры

Создадим объект разделяемой памяти с именем /tmp/myshm объемом 123 456 байт в системе Digital Unix 4.0B:

alpha % shmcreate /tmp/myshm 123456

alpha % ls –l /tmp/myshm

– rw-r--r-- 1 rstevens system 123456 Dec 10 14:33 /tmp/myshm

alpha % od –c /tmp/myshm

0000000 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0

*

0361100

Мы

видим, что файл с указываемым при создании объекта разделяемой памяти именем появляется в файловой системе. Используя программу od, мы можем выяснить, что после создания файл целиком заполнен нулями (восьмеричное число 0361100 — сдвиг, соответствующий байту, следующему за последним байтом файла, — эквивалентно десятичному 123 456).

Запустим программу shmwrite и убедимся в правильности записываемых значений с помощью программы od:

alpha % shmwrite /tmp/myshm

alpha * od –x /tmp/myshm | head-4

0000000 0100 0302 0504 0706 0908 0b0a 0d0c 0f0e

0000020 1110 1312 1514 1716 1918 1b1a 1d1c 1f1e

0000040 2120 2322 2524 2726 2928 2b2a 2d2c 2f2e

0000060 3130 3332 3534 3736 3938 3b3a 3d3c 3f3e

alpha % shmread /tmp/myshm

alpha % shmunlink /tmp/myshm

Мы проверили содержимое разделяемой памяти и с помощью shmread, а затем удалили объект, запустив программу shmunlink.

Если теперь мы запустим программу shmcreate в Solaris 2.6, то увидим, что файл указанного размера создается в каталоге /tmp:

solaris % shmcreate –e /testshm 123

solaris % ls-l/tmp/.*testshm*

– rw-r--r-- 1 rstevens other1 123 Dec 10 14:40 /tmp/.SHMtestshm

Пример

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

Листинг 13.5. Разделяемая память может начинаться с разных адресов в разных процессах

//pxshm/test3.c

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5 int fd1, fd2, *ptr1, *ptr2;

6 pid_t childpid;

7 struct stat stat;

8 if (argc != 2)

9 err_quit("usage: test3 <name>");

10 shm_unlink(Px_ipc_name(argv[1]));

11 fd1 = Shm_open(Px_ipc_name(argv[1]), O_RDWR | O_CREAT | O_EXCL, FILE_MODE);

12 Ftruncate(fd1, sizeof(int));

13 fd2 = Open("/etc/motd", O_RDONLY);

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