Сборка правдоподобного ответа из комментариев - так что это Wiki сообщества с самого начала.(Если Оли дает ответ, проголосуйте за него вместо этого!)
Оли Чарльзуорт дал, вероятно, суть проблемы:
- Я подозреваю, что вы создали состояние гонки в направлении, противоположном тому, что вы ожидали.Ребенок отправил SIGUSR1 родителю до того, как родитель достиг
pause()
.
ouah , точно отмеченных:
- Объект, общий для сигналаобработчик и код не-обработчика (ваши логические объекты) должны иметь тип
volatile sig_atomic_t
, в противном случае код не определен.
Тем не менее, POSIX допускает немного большую гибкость, чем стандартный C, что можетбыть сделано внутри обработчика сигнала.Мы могли бы также отметить, что C99 предоставляет <stdbool.h>
для определения типа bool
.
Оригинальный постер прокомментировал:
Я не вижу, как я могу убедиться, чтоparent сначала выполняет вызов pause()
, не используя sleep()
в child (что ничего не гарантирует).Есть идеи?
Предложение: Использовать usleep()
(µ-сон или сон в микросекундах) или nanosleep()
(сон в наносекундах)?
Или использовать другую синхронизациюмеханизм, такой как:
- родительский процесс создает FIFO;
- fork ();
- дочерний элемент открывает FIFO для записи (блокировка, пока не будет читатель);
- parent открывает FIFO для чтения (блокирует до тех пор, пока не будет записывающее устройство);
- , когда разблокировано, потому что
open()
вызывает возврат, оба процесса просто закрывают FIFO; - родительскийудаляет FIFO.
Обратите внимание, что обмен данными между двумя процессами через FIFO отсутствует;код просто полагается на ядро, чтобы блокировать процессы, пока не появятся читатель и писатель, поэтому оба процесса готовы к работе.
Другая возможность состоит в том, что родительский процесс может попытаться if (siguser1setted == FALSE) pause();
уменьшитьокно для состояния гонки.Тем не менее, это только уменьшает окно;это не гарантирует, что состояние гонки не может возникнуть.То есть применяется закон Мерфи, и сигнал может поступать между завершением теста и временем выполнения pause()
.
Все это говорит о том, что сигналы не являются очень хорошим механизмом IPC.Их можно использовать для IPC, но на самом деле их редко следует использовать для синхронизации.
Кстати, нет необходимости проверять возвращаемое значение любой из функций семейства exec*()
.Если системный вызов возвращается, он завершился неудачей.
И спрашивающий снова спросил:
Не лучше ли использовать семафоры POSIX, совместно используемые процессами?
Семафоры, безусловно, были бы еще одним действительным механизмом синхронизации двух процессов.Поскольку мне, конечно, придется просматривать страницы справочника для семафоров, тогда как я помню, как использовать FIFO, не глядя, я не уверен, что на самом деле буду их использовать, но создание и удаление FIFO имеет свои собственные проблемы.так что не ясно, что это в любом случае «лучше» (или «хуже»);просто другой.Это mkfifo()
, open()
, close()
, unlink()
для FIFO против sem_open()
(или sem_init()
), sem_post()
, sem_wait()
, sem_close()
и, возможно, sem_unlink()
(или * 1083)*) для семафоров.Возможно, вам стоит подумать о регистрации функции «удаление FIFO» или «очистка семафора» с помощью atexit()
, чтобы убедиться, что FIFO или семафор уничтожен при максимально возможном количестве обстоятельств.Тем не менее, это, вероятно, OTT для тестовой программы.