9 return(-1);
10 }
11 if ((n = pthread_mutex_lock(&sem->sem_mutex)) != 0) {
12 errno = n;
13 return(-1);
14 }
15 *pvalue = sem->sem_count;
16 pthread_mutex_unlock(&sem->sem_mutex);
17 return(0);
18 }
Из этой реализации видно, что семафорами пользоваться проще, чем взаимными исключениями и условными переменными.
10.16. Реализация с использованием семафоров System V
Приведем еще один пример реализации именованных семафоров Posix — на этот раз с использованием семафоров System V. Поскольку семафоры System V появились раньше, чем семафоры Posix, эта реализация позволяет использовать последние в системах, где их поддержка не предусмотрена производителем.
ПРИМЕЧАНИЕ
Семафоры System V описаны в главе 11. Этот раздел можно пропустить при первом чтении, с тем чтобы вернуться к нему по прочтении 11 главы.
Начнем, как обычно, с заголовочного файла semaphore.h (листинг 10.36), который определяет фундаментальный тип данных sem_t.
//my_pxsem_svsem/semaphore.h
1 /* фундаментальный тип данных */
2 typedef struct {
3 int sem_semid; /* идентификатор семафора System V */
4 int sem_magic; /* магическое значение, если семафор открыт */
5 } mysem_t;
6 #define SEM_MAGIC 0x45678923
7 #ifdef SEM_FAILED
8 #undef SEM_FAILED
9 #define SEM_FAILED ((mysem_t *)(-1)) /* исключаем предупреждения компилятора */
10 #endif
11 #ifndef SEMVMX
12 #define SEMVMX 32767 /* исторически сложившееся максимальное значение для семафора System V */
13 #endif
1-5 Мы реализуем именованный семафор Posix с помощью набора семафоров System V, состоящего из одного элемента. Структура данных семафора содержит идентификатор семафора System V и магическое число (обсуждавшееся в связи с листингом 10.21).
Функция sem_open
В листинге 10.37 приведен текст первой половины функции sem_open, которая создает новый семафор или открывает существующий.
//my_pxsem_svsem/sem_open. с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 #include
4 #define MAX_TRIES 10 /* количество попыток инициализации */
5 mysem_t *
6 mysem_open(const char *pathname, int oflag, … )
7 {
8 int i, fd, semflag, semid, save_errno;
9 key_t key;
10 mode_t mode;
11 va_list ap;
12 mysem_t *sem;
13 union semun arg;
14 unsigned int value;
15 struct semid_ds seminfo;
16 struct sembuf initop;
17 /* режим доступа для sem_open() без O_CREAT не указывается; угадываем */
18 semflag = SVSEM_MODE;
19 semid = –1;
20 if (oflag & O_CREAT) {
21 va_start(ap, oflag); /* инициализируем ар последним явно указанным аргументом */
22 mode = va_arg(ap, va_mode_t);
23 value = va_arg(ap, unsigned int);
24 va_end(ap);
25 /* преобразуем в ключ, который будет идентифицировать семафор System V */
26 if ((fd = open(pathname, oflag, mode)) == –1)
27 return(SEM_FAILED);
28 close(fd);
29 if ((key = ftok(pathname, 0)) == (key_t) –1)
30 return(SEM_FAILED);
31 semflag = IPC_CREAT | (mode & 0777);
32 if (oflag & O_EXCL)