10 sem->sem_magic = 0; /* чтобы семафор нельзя было больше использовать */
11 if (close(sem->sem_fd[0]) == –1 || close(sem->sem_fd[1]) == –1) {
12 free(sem);
13 return(-1);
14 }
15 free(sem);
16 return(0);
17 }
Функция sem_unlink
Функция sem_unlink, текст которой приведен в листинге 10.24, удаляет из файловой системы наш семафор. Она просто вызывает unlink.
//my_pxsem_fifo/sem_unlink. с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 int
4 mysem_unlink(const char *pathname)
5 {
6 return(unlink(pathname));
7 }
Функция sem_post
В листинге 10.25 приведен текст функции sem_post, которая увеличивает значение семафора.
11-12 Мы записываем один байт в FIFO. Если канал был пуст, это приведет к возобновлению выполнения всех процессов, заблокированных в вызове read для этого канала.
//my_pxsem_fifo/sem_post.с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 int
4 mysem_post(mysem_t *sem)
5 {
6 char c;
7 if (sem->sem_magic != SEM_MAGIC) {
8 errno = EINVAL;
9 return(-1);
10 }
11 if (write(sem->sem_fd[1], &c, 1) == 1)
12 return(0);
13 return(-1);
14 }
Функция sem_wait
Последняя функция для работы с именованными семафорами Posix — sem_wait. Ее текст приведен в листинге 10.26.
//my_pxsem_fifo/sem_wait.с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 int
4 mysem_wait(mysem_t *sem)
5 {
6 char c;
7 if (sem->sem_magic != SEM_MAGIC) {
8 errno = EINVAL;
9 return(-1);
10 }
11 if (read(sem->sem_fd[0], &c, 1) == 1)
12 return(0);
13 return(-1);
14 }
11-12 Мы считываем 1 байт из канала FIFO, причем работа приостанавливается, если канал пуст.
Мы еще не реализовали функцию sem_trywait, но это можно сделать, установив флаг отключения блокировки для канала и используя обычный вызов read. Мы также не реализовали функцию sem_getvalue. В некоторых реализациях при вызове функции stat или fstat возвращается количество байтов в именованном или неименованном канале, причем оно помещается в поле st_size структуры stat. Однако это не гарантируется стандартом Posix и, следовательно, не обязательно будет работать в других системах. Пример реализации этих двух функций для работы с семафорами Posix приведен в следующем разделе.
10.15. Реализация с помощью отображения в память
Теперь займемся реализацией именованных семафоров Posix с помощью отображаемых в память файлов вместе со взаимными исключениями и условными переменными Posix. Реализация, аналогичная данной, приведена в разделе В.11.3 Обоснования стандарта IEEE 1996 [8].
ПРИМЕЧАНИЕ
Отображаемые в память файлы описаны в главах 12 и 13. Данный раздел можно отложить, с тем чтобы вернуться к нему после прочтения этих глав.
Прежде всего приведем текст нашего заголовочного файла semaphore.h (листинг 10.27), в котором определяется фундаментальный тип sem_t.
1-7 Структура данных семафора содержит взаимное исключение, условную переменную и беззнаковое целое, в котором хранится текущее значение семафора. Как уже говорилось в связи с листингом 10.21, поле sem_magiс получает значение SEM_MAGIC при инициализации структуры.
//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;