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.
Листинг 10.36. Заголовочный файл semaphore.h
//my_pxsem_svsem/semaphore.h
1 /* фундаментальный тип данных */
2 typedef struct {
3 int sem_semid; /* идентификатор семафора System V */
4 int sem_magic; /* магическое значение, если семафор открыт */
12 #define SEMVMX 32767 /* исторически сложившееся максимальное значение для семафора System V */
13 #endif
Тип данных sem_t
1-5 Мы реализуем именованный семафор Posix с помощью набора семафоров System V, состоящего из одного элемента. Структура данных семафора содержит идентификатор семафора System V и магическое число (обсуждавшееся в связи с листингом 10.21).
Функция sem_open
В листинге 10.37 приведен текст первой половины функции sem_open, которая создает новый семафор или открывает существующий.
Листинг 10.37. Функция sem_open: первая часть
//my_pxsem_svsem/sem_open. с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 #include <stdarg.h> /* для списков аргументов переменной длины */
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)
33 semflag |= IPC_EXCL;
34 /* создаем семафор System V с флагом IPC_EXCL */