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

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

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

ПРИМЕЧАНИЕ

Детали реализации mmap и связь этого вызова с механизмами реализации виртуальной памяти описаны в [14] для 4.4BSD и [6] для SVR4.

12.3. Увеличение счетчика

в отображаемом в память файле

Изменим программу в листинге 12.1 (которая не работала) таким образом, чтобы родительский и дочерний процессы совместно использовали область памяти, в которой хранится счетчик. Для этого используем отображение файла в память вызовами open и mmap, В листинге 12.2 приведен текст новой программы.

Листинг 12.2. Родительский и дочерний процессы увеличивают значение счетчика в разделяемой памяти

shtti/incr2.c

1 finclude unpipc.h

2 fdefine SEMJAME ttiysetti

3 int

4 ttiainCint argc. char **argv)

6 int fd, i, nloop, zero = 0,-

7 int *ptr:

8 setti t *ttiutex;

9 if (argc != 3)

10 err quit( usage: incr2 <pathnattie>.<floops> ):

11 nloop = atoi(argv[2]):

12 /* открываем файл, инициализируем нулем и отображаем в память */

13 fd = Open(argv[l], 0 ROWR 0 CREAT, FILE M(X)E);

14 Write(fd, &zero, sizeof(int));

15 ptr - Minap(NULL, sizeof (int), PROT REAO PROT WRITE, MAP SHAREO, fd, 0);

16 Close(fd):

17 /* создаем, инициализируем и отключаем семафор */

18 ttiutex - Setti open(Px ipc nattie(SEM NAME), 0 CREAT OJXCL, FILE M(X)E, 1):

19 Sem unl i nk( Px i pc nattie(SEM NAME)) ,-

20 setbuf(stdout, NULL); /* stdout не буферизуется */

21 if (ForkO - 0) { /* дочерний процесс */

22 for (i = 0: i < nloop: i++) {

23 Setti wait (ttiutex):

24 printf( child: %й\п . (*ptr)++);

25 Setti post( ttiutex):

26 }



27 exit(O);

28 }

29 /* родительский процесс */

30 for (i = 0; 1 < nloop; i++) {

31 Sem wait(mutex):

32 printf( parent: %d\n . (*ptr)++);

33 SemjDOSt(mutex):

34 }

35 exit(O):

36 }

Новый аргумент командной строки

11-14 Из командной строки теперь считывается еще один аргумент, задающий полное имя файла, который будет отображен в память. Мы открываем файл для чтения и записи, причем если файл не существует, он будет создан, а затем инициализируем файл нулем.

Вызов mmap и закрытие дескриптора

15-16 Вызов mmap позволяет отобразить открытый файл в адресное пространство процесса. Первый аргумент является нулевым указателем, при этом система сама выбирает адрес начала отображаемого сегмента. Длина файла совпадает с размером целого числа. Устанавливается доступ на чтение и запись. Четвертый аргумент имеет значение MAP SHARED, что позволяет процессам видеть изменения, вносимые друг другом. Функция возвращает адрес начала участка разделяемой памяти, мы сохраняем его в переменной ptr.

fork

20-34 Мы отключаем буферизацию стандартного потока вывода и вызываем fork. И родительский, и дочерний процессы по очереди увеличивают значение целого, на которое указывает ptr.

Отображенные в память файлы обрабатываются при вызове fork специфическим образом в том смысле, что созданные родительским процессом отображения наследуются дочерним процессом. Следовательно, открыв файл и вызвав шар с флагом MAP SHARED, мы получили область памяти, совместно используемую родительским и дочерним процессами. Более того, поскольку эта общая область на самом деле представляет собой отображенный файл, все изменения, вносимые в нее (область памяти, на которую указывает ptr, - размером sizeof (int)), также действуют и на содержимое реального файла (имя которого было указано в командной строке).

Запустив эту программу на выполнение, мы увидим, что память, на которую указывает ptr, действительно используется совместно родительским и дочерним процессами. Приведем значения счетчика перед переключением процессов:

Solaris % 1псг2 /tmp/temp.l 10000

child: О запускается дочерний процесс

child: 1

child: 128



child: 129 parent: 130 parent: 131

parent: 636 parent: 637 child: 638 child: 639

дочерний процесс приостанавливается, запускается родительский процесс

родительский процесс приостанавливается, запускается дочерний процесс

child: 1517 child: 1518 parent parent

1519 1520

дочерний процесс приостанавливается, запускается родительский процесс

parent: 19999 последняя строка вывода Solaris od -D /tmp/temp.l 0000000 0000020000 0000004

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

На рис. 12.6 изображена схема, отличающаяся от рис. 12.4. Здесь используется разделяемая память и показано, что семафор также используется совместно. Семафор мы изобразили размещенным в ядре, но для семафоров Posix это не обязательно. В зависимости от реализации семафор может обладать различной живучестью, но она должна быть по крайней мере не меньше живучести ядра. Семафор может быть реализован также через отображение файла в память, что мы продемонстрировали в разделе 10.15.

выполняется зта команда родительского процесса

родительский процесс

infptn

if(Fork()==0) { Г child */

Г parent */

разделяемая память

счетчик


выполняется эта команда - дочернего процесса

дочерний процесс

int *ptr;

if(Fork()==0) { /* child */

/* parent */

процесс ядро

семафор:

О или 1

Рис. 12.6. Родительский и дочерний процессы используют разделяемую память и общий семафор



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.
Копирование материалов разрешено исключительно при условии цититирования.