ПРИМЕЧАНИЕ 4
Стандарт Posix.1 предупреждает, что для обращения к размещаемым в памяти семафорам можно использовать только указатель, являющийся аргументом при вызове sem_init. Использование копий этого указателя может привести к неопределенным результатам.
Функция sem_init возвращает –1 в случае ошибки, но она не возвращает 0 в случае успешного завершения. Это действительно странно, и примечание в Обосновании Posix. 1 говорит, что в будущих версиях функция, возможно, начнет возвращать 0 в случае успешного завершения.
Размещаемый в памяти семафор может быть использован в тех случаях, когда нет необходимости использовать имя, связываемое с именованным семафором. Именованные семафоры обычно используются для синхронизации работы неродственных процессов. Имя в этом случае используется для идентификации семафора.
В связи с табл. 1.1 мы говорили о том, что семафоры, размещаемые в памяти, обладают живучестью процесса, но на самом деле их живучесть зависит от типа используемой разделяемой памяти. Размещаемый в памяти семафор не утрачивает функциональности до тех пор, пока память, в которой он размещен, еще доступна какому-либо процессу.
■ Если размещаемый в памяти семафор совместно используется потоками одного процесса (аргумент
■ Если размещаемый в памяти семафор совместно используется несколькими процессами (аргумент
Предупреждаем, что нижеследующий код не работает так, как ожидается:
sem_t mysem;
Sem_init(&mysem, 1.0); /* 2-й аргумент 1 –> используется процессами */
if (Fork() == 0) { /* дочерний процесс */
…
Sem_post(&mysem);
}
Sem_wait(&mysem); /* родительский процесс: ожидание дочернего */
Проблема тут в том, что семафор не располагается в разделяемой памяти (см. раздел 10.12). Память, как правило, не делится между дочерним и родительским процессами при вызове fork. Дочерний процесс запускается с копией памяти родителя, но это не то же самое, что разделяемая память.
В качестве иллюстрации перепишем наш пример решения задачи производителей и потребителей из листингов 10.8 и 10.9 для использования размещаемых в памяти семафоров Posix. В листинге 10.11 приведен текст новой программы.
//pxsem/prodcons2.c
1 #include "unpipc.h"
2 #define NBUFF 10
3 int nitems; /* только для чтения производителем и потребителем */
4 struct { /* общие данные производителя и потребителя */
5 int buff[NBUFF];
6 sem_t mutex, nempty, nstored; /* семафоры, а не указатели */
7 } shared;
8 void *produce(void *), *consume(void *);
9 int
10 main(int argc, char **argv)
11 {
12 pthread_t tid_produce, tid_consume;
13 if (argc != 2)
14 err_quit("usage: prodcons2 <#items>");
15 nitems = atoi(argv[1]);
16 /* инициализация трех семафоров */
17 Sem_init(&shared.mutex, 0, 1);
18 Sem_init(&shared.nempty, 0, NBUFF);
19 Sem_init(&shared.nstored, 0, 0);
20 Set_concurrency(2);