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

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

17 SemctKsemid, О, SETVAL, arg);

18 } else if (errno == EEXIST) {

19 /* семафор создан другим процессом, убедимся, что он проинициализирован */

20 semid - Semget(Ftok(LOCK PATH. 0), 1, SVSEM MODE):

21 arg.buf - &seminfo;

22 for (i = 0; i < MAXJRIES; i++) {

23 SemctKsemid, 0, IPC STAT, arg);

24 if (arg.buf->sem otime != 0)

25 goto init;

26 sleep(l);

27 }

28 err quit( semget OK, but semaphore not initialized );

29 } else

30 err sys( semget error );

31 init:

32 initflag = 1:

33 postop.sem num = 0; /* инициализируем две структуры semopO*/

34 postop.sem op = 1:

35 postop.sem f1g - SEM UNDO:

36 waitop.sem num = 0:

37 waitop.sem op - -1:

38 waitop.semjig - SEMJNDO:

39 }

40 Semop(semid, &waitop, 1); /* уменьшим на 1 */

41 }

42 void

43 my un1ock(int fd)

44 {

45 Semop(semid, &postop, 1): /* увеличим на 1*/

46 }

Попытка исключающего создания

13-17 Нам нужно гарантировать, что только один процесс проинициализирует семафор, поэтому при вызове semget мы указываем флаги IPCJREAT IPCJXCL, Если этот вызов оказывается успешным, процесс вызывает semctl для инициализации семафора значением 1. Если мы запустим несколько процессов одновременно и все они вызовут функцию mylock, только один из них создаст семафор (предполагается, что он еще не существует) и проинициализирует его.

Семафор уже существует, мы его открываем

18-20 Если первый вызов semget возвращает ошибку EEXIST, процесс вызывает semget еще раз, но уже без флагов IPCJREAT и IPCJXCL,

Ожидание инициализации семафора

21-28 В этой программе возникает такая же ситуация гонок, как и обсуждавшаяся в разделе 11,2, когда мы говорили об инициализации семафоров System V вообще. Для исключения такой ситуации все процессы, которые обнаруживают, что семафор уже создан, вызывают semctl с командой IPCSTAT, проверяя значение



semotime данного семафора. Когда это значение становится ненулевым, мы можем быть уверены, что создавший семафор процесс проинициализировал его и вызвал semop (этот вызов находится в конце функции) успешно. Если значение этого поля оказывается нулевым (что должно происходить крайне редко), мы приостанавливаем выполнение процесса на одну секунду вызовом sl еер, а затем повторяем попытку. Число попыток мы ограничиваем, чтобы процесс не заснул навсегда.

Инициализация структур sembuf

33-38 Как отмечалось ранее, конкретный порядок полей структуры sembuf зависит от реализации, поэтому статически инициализировать ее нельзя. Вместо этого мы выделяем место под две такие структуры и присваиваем значения их полям во время выполнения программы, когда процесс вызывает ту 1 оск в первый раз. При этом мы указываем флаг SEM UNDO, чтобы ядро сняло блокировку, если процесс завершит свою работу, не сняв ее самостоятельно (см. упражнение 10,3),

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

11.7. Ограничения семафоров System V

На семафоры System V накладываются определенные системные ограничения, так же, как и на очереди сообщений. Большинство этих ограничений были связаны с особенностями реализации System V (раздел 3,8), Они показаны в табл, 11,1, Первая колонка содержит традиционное для System V имя переменной ядра, в которой хранится соответствующее ограничение.

Таблица 11.1. Типичные значения ограничений для семафоров System V

Описание

DUnix4.0B

Solaris 2.6

semmni

Максимальное количество наборов семафоров в системе

semmsl

Максимальное количество семафоров в наборе

semmns

Максимальное количество семафоров в системе

semopm

Максимальное количество операций за один вызов semop

semmnu

Максимальное количество структур undo в системе

semume

Максимальное количество записей в структуре undo

semvmx

Максимальное значение семафора

32 767

32 767

semaem

Максимальное значение корректировки при выходе

16 384

16 384

В Digital Unix 4,0В никакого ограничения на semmnu не существует.



Пример

Программа в листинге 11,7 позволяет определить ограничения, приведенные втабл, 11,1,

Листинг 11.7. Определение системных ограничений на семафоры System V

svsem/limits.с

1 finclude unpipc.h

2 /* максимальные величины, выше которых ограничение не проверяется */

3 fdefine MAX NIDS 4096 /* максимальное количество идентификаторов семафоров */

4 fdefine MAX VALUE 1024*1024 /* максимальное значение семафора */

5 fdefine MAX MEMBERS 4096 /* максимальное количество семафоров в наборе */

6 fdefine MAX NOPS 4096 /* максимальное количество операций за вызов semop */

7 fdefine MAX NPROC Sysconf( SC CHILD MAX)

8 int

9 main(int argc, char **argv)

10 {

11 int i, j, semid, sid[MAX NIDS], pipefd[2]:

12 int semmni, semvmx, semmsl, semmns, semopn. semaem, semume, semmnu:

13 pid t *chi1d;

14 union semun arg:

15 struct sembuf ops[MAX NOPS]:

16 /* сколько наборов с одним элементом можно создать? */

17 for (i = 0: i <- MAX NIDS: i++) {

18 sid[i] = semget(IPC PRIVATE, 1. SVSEM MODE IPC CREAT):

19 if (sid[i] == -1) {

20 semmni = i:

21 printf( M identifiers open at once\n , semmni):

22 break:

23 }

24 }

25 /* перед удалением находим максимальное значение, используя sid[0] */

26 for (j = 7: j < MAXJALUE: j += 8) {

27 arg. val = j:

28 if (semct1(sid[0], 0, SETVAL, arg) ==-1) {

29 semvmx = j - 8:

30 printf( max semaphore value = %й\п . semvmx):

31 break:

32 }

33 }

34 for (j = 0: j < i; j++)

35 SemctUsid[j], 0. IPC RMID):

36 /* определяем максимальное количество семафоров в наборе */

37 for (i = 1: i <= MAX MEMBERS; i++) {

38 semid = semget(IPC PRIVATE, i, SVSEM MODE IPC CREAT):

39 if (semid -= -1) {

40 semmsl = i-1:

41 printf( max of d members per set\n , semmsl):

42 break:

43 }

44 SemctKsemid, 0, IPC RMID):



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