Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 [ 111 ] 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

Листинг 13.3 (продолжение)

14 MAPJHARED. fd. 0):

15 Close(fd):

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

17 for (i = 0: i < stat.st s1ze: i++)

18 *ptr++ = i X 256:

19 exitCO):

20 }

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

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

Программа shmread

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

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

pxsfitti/slittiread.c

1 finclude unpipcli

2 int

3 ttiainCint argc. char **argv)

5 int i. fd:

6 struct stat stat:

7 unsigned char с *ptr:

8 if Cargc != 2)

9 err quitC usage: shttiread <nattie> ):

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

11 fd = Shtti openCargv[l]. 0 RDONLY. FILE MODE):

12 FstatCfd. &stat):

13 ptr = MttiapCNULL. stat.st size. PROTJEAD.

14 MAPJHARED. fd. 0):

15 CloseCfd):

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

17 for Ci = 0: i < stat.st size: i++)

18 if С Cc = *ptr++) != Ci X 256))

19 err retC ptr[ d] = Хй . i. с):

20 exitCO):

21 }

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

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



Примеры

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

alpha % shmcreate /tmp/myshm 123456 alpha Is -1 /tmp/myshm

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

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 ObOa OdOc OfOe 0000020 1110 1312 1514 1716 1918 Ibla Idle Ifle 0000040 2120 2322 2524 2726 2928 2b2a 2d2c 2f2e 0000060 3130 3332 3534 3736 3938 ЗЬЗа 3d3c 3f3e alpha % shmread /tmp/myshm alpha % shmunlink /tmp/myshm

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

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

Solaris % shmcreate -е /testshm 123 Solaris * Is -1 /tmp/.*testshm*

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

Пример

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

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

pxshm/test3.c

1 finclude unpipc.h

2 int

3 mainCint argc. char **argv)

5 int fdl. fd2. *ptrl. *ptr2:

6 pid t childpid: продолжение



Листинг 13.5 (продолжение) 1 struct stat stat:

8 if (argc != 2)

9 err quit( usage: tests <nattie> ):

10 slitti unlinl<(Px ipc nanie(argv[l]));

11 fdl = Slitti open(PxJpc nanie(argv[l]). OJDWR OJREAT OJXCL. FILE IDE):

12 Ftruncate(fdl. sizeof(int)):

13 fd2 = Open( /etc/ttiotd . OJDONLY):

14 Fstat(fd2. &stat):

15 if ( (cfiildpid = Forl<()) - 0) {

16 /* дочерний процесс */

17 ptr2 = Mmap(NULL. stat.st size. PROTJEAD. MAPJHARED. fd2. 0):

18 ptrl = Mmap(NULL. sizeof(int). PROTJEAD PROTJRITE.

19 MAPJHARED. fdl. 0):

20 printf( cliild: sfitti ptr = p. motd ptr = p\n . ptrl. ptr2):

21 sleep(5):

22 printf( sliared memory integer = d\n . *ptrl):

23 exit(O):

24 }

25 /* родительский процесс: вызовы mmap следуют в обратном порядке */

26 ptrl = Mmap(NULL. sizeof(int). PROTJEAD PROTJRITE. MAPJHARED. fdl. 0):

27 ptr2 = Mmap(NULL. stat.st size. PROTJEAD. MAPJHARED. fd2. 0):

28 printf ( parent: slim ptr = p. motd ptr = p\n . ptrl. ptr2):

29 *ptrl = 777:

30 Waitpid(cliildpid. NULL. 0):

31 exit(O):

32 }

10-14 Создаем сегмент разделяемой памяти с именем, принимаемым в качестве аргумента командной строки. Его размер устанавливается равным размеру целого. Затем открываем файл /etc/motd.

15-30 После вызова f ог1< и родительский, и дочерний процессы вызывают mmap дважды, но в разном порядке. Каждый процесс выводит начальный адрес каждой из областей памяти. Затем дочерний процесс ждет 5 секунд, родительский процесс помещает значение 777 в область разделяемой памяти, после чего дочерний процесс считывает и выводит это значение.

Запустив эту программу, мы убедимся, что объект разделяемой памяти начинается с разных адресов в пространствах дочернего и родительского процессов:

Solaris % test3 test3.data

parent: slim ptr = еееЗОООО, motd ptr = eee20000 cfiild: slim ptr = eee20000. motd ptr = еееЗОООО sfiared memory integer = 777

Несмотря на разницу в начальных адресах, родительский процесс успешно помещает значение 777 по адресу ОхеееЗОООО, а дочерний процесс благополучно считывает его по адресу Охеее20000. Указатели ptrl в родительском и дочернем процессах указывают на одну и ту же область разделяемой памяти, хотя их значения в этих процессах различны.



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 [ 111 ] 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.