Теперь займемся реализацией именованных семафоров Posix с помощью отображаемых в память файлов вместе со взаимными исключениями и условными переменными Posix. Реализация, аналогичная данной, приведена в разделе В.11.3 Обоснования стандарта IEEE 1996 [8].
ПРИМЕЧАНИЕ
Отображаемые в память файлы описаны в главах 12 и 13. Данный раздел можно отложить, с тем чтобы вернуться к нему после прочтения этих глав.
Прежде всего приведем текст нашего заголовочного файла semaphore.h (листинг 10.27), в котором определяется фундаментальный тип sem_t.
Тип sem_t
1-7 Структура данных семафора содержит взаимное исключение, условную переменную и беззнаковое целое, в котором хранится текущее значение семафора. Как уже говорилось в связи с листингом 10.21, поле sem_magiс получает значение SEM_MAGIC при инициализации структуры.
Листинг 10.27. Заголовочный файл semaphore.h
//my_pxsem_mmap/semaphore.h
1 /* фундаментальный тип */
2 typedef struct {
3 pthread_mutex_t sem_mutex; /* блокируется при проверке и изменении значения семафора */
4 pthread_cond_t sem_cond; /* при изменении нулевого значения */
5 unsigned int sem_count; /* значение семафора */
6 int sem_magic; /* магическое значение, если семафор открыт */
7 } mysem_t;
8 #define SEM_MAGIC 0x67458923
9 #ifdef SEM_FAILED
10 #undef SEM_FAILED
11 #define SEM_FAILED ((mysem_t *)(-1)) /* чтобы избежать предупреждений компилятора */
12 #endif
Функция sem_open
В листинге 10.28 приведен текст первой части функции sem_open, которая может использоваться для создания нового семафора или открытия существующего.
Листинг 10.28. Функция sem_open: первая половина
//my_pxsem_mmap/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 fd, i, created, save_errno;
9 mode_t mode;
10 va_list ap;
11 mysem_t *sem, seminit;
12 struct stat statbuff;
13 unsigned int value;
14 pthread_mutexattr_t mattr;
15 pthread_condattr_t cattr;
16 created = 0;
17 sem = MAP_FAILED; /* [sic] */
18 again:
19 if (oflag & O_CREAT) {
20 va_start(ap, oflag); /* ар инициализируется последним явно указанным аргументом */
21 mode = va_arg(ap, va_mode_t) & ~S_IXUSR;
22 value = va_arg(ap, unsigned int);
23 va_end(ap);
24 /* открываем с указанием флага O_EXCL и установкой бита user-execute */