Главная страница Взаимодействие нетривиальных процессов 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
В 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):
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |