Главная страница Взаимодействие нетривиальных процессов 7 key t key: 8 lf ( (key = ftok(pathname. 0)) == (key t) -1) 9 return(-l): 10 if (unlink(pathname) == -1) 11 return(-l): 12 if ( (semid = semget(key. 1. SVSEM MODE)) == -1) 13 return(-l): 14 if (semcti(semid. 0. IPC RMID) =- -1) 15 return(-l): 16 return(O): 17 } Листинг 10.41. Функция sem post my pxsem svsem/sem post.c 1 finclude unpipc.h 2 finclude semaphore.h 3 int 4 mysem post(mysem t *sem) 6 struct sembuf op: 7 if (sem->sem magic != SEM MAGIC) { 8 errno = EINVAL: 9 return(-l): 10 } 11 op.sem num = 0: 12 op.sem op = 1: 13 op.sem flg = 0: 14 if (semop(sem->sem semid. &op. 1) < 0) 15 return(-l): 16 return(O): 17 } Листинг 10.42. Функция sem wait my pxsem svsem/sem wait.с 1 finclude unpipc.h 2 finclude semaphore.h 3 int 4 mysem wait(mysem t *sem) 6 struct sembuf op; 7 if (sem->sem magic != SEM MAGIC) { 8 errno = EINVAL: 9 return(-l): 10 } 11 op.sem num = 0: 12 op.sem op = -1: 13 op.sem flg = 0: 14 if (semop(sem->sem semid. &op. 1) < 0) 15 return(-l): л продолжение Листинг 10.42 (продолжение) 16 return(O): 17 } Функция sem trywait в листинге 10.43 приведен текст нашей функции sem trywait, которая представляет собой неблокируемую версию sem wa1t. 13 Единственное отличие от функции sem wait из листинга 10.42 заключается в том, что флагу sem flg присваивается значение IPC NOWAIT. Если операция не может быть завершена без блокирования вызвавшего потока, функция semop возвращает ошибку EAGAIN, а это именно тот код, который должен быть возвращен sem trywait, если операция не может быть завершена без блокирования потока. Листинг 10.43. Функция semjrywait my pxsem svsem/sem trywait.с 1 finclude unpipc.h 2 finclude semaphore.h 3 int 4 mysem trywait(mysemj *sem) 5 { 6 struct sembuf op: 7 if (sem->sem magic !- SEM MAGIC) { 8 errno = EINVAL: 9 return(-l): 10 } 11 op.sem num - 0: 12 op.sem op = -1: 13 op. sem Jig = IPCJOWAIT: 14 if (semop(sem->sem semid. &op. 1) < 0) 15 return(-l): 16 return(O): 17 } Функция sem getvalue Последняя функция приведена в листинге 10.44. Это функция sem getvalue, возвращающая текущее значение семафора. 11-14 Текущее значение семафора получается отправкой команды GETVAL функции semctl. Листинг 10.44. Функция sem getvalue my pxsem svsem/sem getvalue. с 1 finclude unpipc.h 2 finclude semaphore.h 3 int 4 iT\ysem getvalue(iT\ysemJ *sem. int *pvalue) 5 { 6 int val: 7 if (sem->sem magic !- SEMJAGIC) {. 8 errno = EINVAL: 9 return(-l): 10 } 11 if ( (vai = semctl(sem->sem semid. 0. GETVAD) < 0) 12 return(-l): 13 *pvalue = vai: 14 return(O): 15 } 10.17. Резюме Семафоры Posix представляют собой семафоры-счетчики, для которых определены три основные операции: 1. Создание семафора. 2. Ожидание изменения значения семафора на ненулевое и последующее умень-щение значения. 3. Увеличение значения семафора на 1 и возобновление выполнения всех процессов, ожидающих его изменения. Семафоры Posix могут быть именованными или неименованными (размещаемыми в памяти). Именованные семафоры всегда могут использоваться отдельными процессами, тогда как размещаемые в памяти должны для этого изначально планироваться как разделяемые между процессами. Эти типы семафоров также отличаются друг от друга по живучести: именованные семафоры обладают по меньщей мере живучестью ядра, тогда как размещаемые в памяти обладают живучестью процесса. Задача производителей и потребителей является классическим примером для иллюстрации использования семафоров. В этой главе первое рещение состояло из одного потока-производителя и одного потока-потребителя; второе рещение имело нескольких производителей и одного потребителя, а последнее рещение допускало одновременную работу и нескольких потребителей. Затем мы показали, что классическая задача двойной буферизации является частным случаем задачи производителей и потребителей с одним производителем и одним потребителем. В этой главе было приведено три примера возможной реализации семафоров Posix. Первый пример был самым простым, в нем использовались каналы FIFO, а большая часть забот по синхронизации ложилась на ядро (функции read и wri te). Следующая реализация использовала отображение файлов в память (аналогично реализации очередей сообщений Posix из раздела 5.8), а также взаимное ис-1слючение и условную переменную (для синхронизации). Последняя реализация была основана на семафорах System V и представляла собой, по сути, удобный интерфейс для работы с ними. Упражнения 1. Измените функции produce и consume из раздела 10.6 следующим образом. Поменяйте порядок двух вызовов Sem wa i t в потребителе, чтобы возникла ситуация зависания (как описано в разделе 10.6). Затем добавьте вызов printf перед
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |