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

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

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

Изменим программу в листинге 12.2 так, чтобы использовались семафоры Posix, размещаемые в памяти (вместо именованных). Разместим такой семафор в разделяемой области памяти. Новая программа приведена в листинге 12.3.

Листинг 12.3. Счетчик и семафор размещены в разделяемой памяти

shm/incr3.c

1 finclude unpipc.h

2 struct shared {

3 setti t mutex: /* взаимное исключение; семафор, размещаемый в памяти */

4 int count; /* и счетчик */

5 } shared;

6 int

7 mainCint argc, char **argv)

9 int fd, i, nloop:

10 struct shared *ptr;

11 if (argc != 3)

12 err quit( usage: incr3 <pathname> <floops> ):

13 nloop = atoi(argv[2]);

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

15 fd - Open(argv[l]. 0 ROWR 0 CREAT. FILE f )E);

16 Write(fd. &shared. sizeof(struct shared));

17 ptr - Mmap(NULL. sizeof(struct shared). PROT READ PROT WRITE,

18 MAP SHAREO, fd, 0):

19 Close(fd);

20 /* инициализация семафора, совместно используемого процессами */

21 Sem init(&ptr->mutex, 1, 1):

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

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

24 for (i - 0; i < nloop; i++) {

25 Sem wait(&ptr->mutex);

26 printf( child: *d\n , ptr->count++);

27 Sem post(&pt r->mutex);

28 }

29 exit(O);

30 }

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

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

33 Sem wait(&ptr->mutex);

34 printf( parent: *d\n , ptr->count++);

35 Sem post(&ptr->mutex);

36 }

37 exit(O);

38 }



Определение структуры, хранящейся в разделяемой памяти

2-5 Помещаем целочисленный счетчик и семафор, защищающий его, в одну структуру. Эта структура будет храниться в разделяемой памяти.

Отображаем в память

14-19 Создается файл для отображения в память, который инициализируется структурой с нулевым значением обоих полей. При этом инициализируется только счетчик, поскольку семафор будет инициализирован позднее вызовом sem init. Тем не менее проще инициализировать всю струетуру нулями, чем только одно целочисленное поле.

Инициализация семафора

20-21 Используем семафор, размещаемый в памяти, вместо именованного. Для его инициализации единицей вызываем sem init. Второй аргумент должен быть ненулевым, чтобы семафор мог совместно использоваться несколькими процессами.

На рис. 12.7 изображена модификация рис. 12.6, где семафор переместился из ядра в разделяемую память.

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

счетчик и семафор

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

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

struct shared *ptr;

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

} Г parent */


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

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

struct shared *ptr;

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

/* parent */

Рис. 12.7. И семафор, и счетчик теперь хранятся в разделяемой памяти

12.4. Неименованное отображение в память в 4.4BSD

Наши примеры из листингов 12.2 и 12.3 работают отлично, но нам приходится создавать файл в файловой системе (аргумент командной строки), вызывать open, записывать нули в файл вызовом write (чтобы проинициализировать его). Если mmap используется для передачи области разделяемой памяти через fork, мы можем упростить эту схему, используя свойства реализации. 1. В версии 4.4BSD предоставляется возможность неименованного отображения в память. При этом полностью пропадает необходимость создавать или от-



крывать файлы. Вместо этого указываются флаги MAP SHARED MAP ANON и дескриптор fd = -1. Сдвиг, задаваемый аргументом offset, игнорируется. Память автоматически инициализируется нулями. Пример использования приведен в листинге 12.4.

2. В версии SVR4 имеется файл /dev/zero, который мы открываем и дескриптор которого указываем при вызове mmap. Это устройство возвращает нули при попытке считывания, а весь направляемый на него вывод сбрасывается. Пример использования приведен в листинге 12.5. (Во многих реализациях, про-изощедщих от BSD, также поддерживается устройство /dev/zero, например в SunOS 4.1.x и BSD/OS 3.1.)

В листинге 12.4 приведена часть листинга 12.2, которая изменяется при переходе к использованию неименованного отображения в память в 4.4BSD.

Листинг 12.4. Отображение в память в 4.4BSD

shtti/i ncr ttiap anon. с

3 int

4 mainCint argc, char **argv)

6 int i. nloop:

7 int *ptr:

8 sem t *mutex:

9 if (argc != 2)

10 err quit( usage: incr map anon <#loops> ):

11 nloop = atoi(argv[l]):

12 /* отображение в память */

13 ptr - Mmap(NULL. sizeof(int), PROT REAO PROT WRITE.

14 MAP SHARED MAP ANON. -1. 0):

6-11 Автоматические переменные fd и zero больше не используются, как и аргумент командной строки, задававший имя создаваемого файла.

12-14 Файл больше не нужно открывать. Вместо этого указывается флаг MAP ANON при вызове mmap, а пятый аргумент этой функции (дескриптор) принимает значение -1.

12.5. Отображение в память в SVR4 с помощью /dev/zero

в листинге 12.5 приведена часть новой версии программы, претерпевшая изменения по сравнению с листингом 12.2 при переходе к использованию отображения с помощью /dev/zero.

Листинг 12.5. Отображение памяти в SVR4 с помощью /dev/zero

shm/incr dev zero.c

3 int

4 main(int argc, char **argv)

6 int fd. i. nloop:

7 int *ptr:

8 sem t *mutex: продолжение-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.
Копирование материалов разрешено исключительно при условии цититирования.