SEM_NSEMS_MAX — максимальное количество одновременно открытых семафоров для одного процесса (Posix требует, чтобы это значение было не менее 256);

SEM_VALUE_MAX — максимальное значение семафора (Posix требует, чтобы оно было не меньше 32767).

Две эти константы обычно определены в заголовочном файле unistd.h и могут быть получены во время выполнения вызовом sysconf, как мы показываем ниже.

<p>Пример: программа semsysconf</p>

Программа в листинге 10.20 вызывает sysconf и выводит два ограничения на семафоры, зависящие от конкретной реализации. 

Листинг 10.20. Вызов sysconf для получения ограничений на семафоры

//pxsem/semsysconf.с

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5  printf("SEM_NSEMS_MAX = %ld, SEM_VALUE_MAX = %ld\n",

6   Sysconf(_SC_SEM_NSEMS_MAX), Sysconf(_SC_SEM_VALUE_MAX));

7  exit(0);

8 }

При запуске этой программы в наших двух тестовых системах получим следующий результат:

solaris % semsysconf

SEMS_NSEMS_MAX = 2147483647, SEM_VALUE_MAX = 2147483647

alpha % semsysconf

SEMS_NSEMS_MAX = 256, SEM_VALUE_MAX = 32767

<p>10.14. Реализация с использованием FIFO</p>

Займемся реализацией именованных семафоров Posix с помощью каналов FIFO. Именованный семафор реализуется как канал FIFO с конкретным именем. Неотрицательное количество байтов в канале соответствует текущему значению семафора. Функция sem_post помещает 1 байт в канал, a sem_wait считывает его оттуда (приостанавливая выполнение процесса, если канал пуст, а именно этого мы и хотим). Функция sem_open создает канал FIFO, если указан флаг O_CREAT; открывает его дважды (один раз на запись, другой — на чтение) и при создании нового канала FIFO помещает в него некоторое количество байтов, указанное в качестве начального значения.

ПРИМЕЧАНИЕ

Этот и последующие разделы данной главы содержат усложненный материал, который можно при первом чтении пропустить.

Приведем текст нашего заголовочного файла semaphore.h, определяющего фундаментальный тип sem_t (листинг 10.21).

Листинг 10.21. Заголовочный файл semaphore.h

//my_pxsem_fifo/semaphore.h

1  /* фундаментальный тип */

2  typedef struct {

3   int sem_fd[2]; /* два дескриптора fd: [0] для чтения, [1] для записи */

4   int sem_magic; /* магическое число */

5  } mysem_t;

6  #define SEM_MAGIC 0x89674523

7  #ifdef SEM_FAILED

8  #undef SEM_FAILED

9  #define SEM_FAILED ((mysem_t *)(-1)) /* чтобы компилятор не выдавал предупреждений*/

10 #endif

Тип данных sem_t

1-5 Новая структура данных содержит два дескриптора, один из которых предназначен для чтения из FIFO, а другой — для записи. Для единообразия мы храним оба дескриптора в массиве из двух элементов, в котором первый дескриптор всегда открыт на чтение, а второй — на запись.

Поле sem_magiс содержит значение SEM_MAGIC, если структура проинициализирована. Это значение проверяется всеми функциями, которым передается указатель на тип sem_t, чтобы гарантировать, что передан был действительно указатель на заранее инициализированную структуру, а не на произвольную область памяти. При закрытии семафора этому полю присваивается значение 0. Этот метод хотя и не совершенен, но дает возможность обнаружить некоторые ошибки при написании программ.

<p>Функция sem_open</p>

В листинге 10.22 приведен текст функции sem_open, которая создает новый семафор или открывает существующий.

Листинг 10.22. Функция sem_open

//my_pxsem_fifo/sem_open.с

1  #include "unpipc.h"

2  #include "semaphore.h"

3  #include stdarg.h /* для произвольного списка аргументов */

4  mysem_t *

5  mysem_open(const char *pathname, int oflag, …)

6  {

7   int i, flags, save_errno;

8   char c;

9   mode_t mode;

10  va_list ap;

11  mysem_t *sem;

12  unsigned int value;

13  if (oflag O_CREAT) {

14   va_start(ap, oflag); /* ар инициализируется последним аргументом */

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже