Я реализую пользовательские потоки в ядре Linux 2.4, и я использую ualarm для вызова контекстных переключений между потоками.
У нас есть требование, чтобы наши функции библиотеки потока были непрерываемы механизмом контекстного переключения для потоков, таким образом, я изучил сигналы блокировки и узнал, что использование sigprocmask является стандартным способом сделать это.
Однако похоже, что я должен сделать довольно много для реализации этого:
sigset_t new_set, old_set;
sigemptyset(&new_set);
sigaddset(&new_set, SIGALRM);
sigprocmask(SIG_BLOCK, &new_set, &old_set);
Это блокирует SIGALARM, но он делает это с 3 вызовами функции! Много может произойти во время, которое требуется, чтобы эти функции работали, включая отправляемый сигнал. Лучшая идея я должен был смягчить это, временно отключала ualarm, как это:
sigset_t new_set, old_set;
time=ualarm(0,0);
sigemptyset(&new_set);
sigaddset(&new_set, SIGALRM);
sigprocmask(SIG_BLOCK, &new_set, &old_set);
ualarm(time, 0);
Который прекрасен за исключением того, что это чувствует себя подробным. Нет ли лучший способ сделать это?
Как указывает WhirlWind , функции набора сигналов довольно легкие и даже могут быть реализованы как макросы; и вы также можете просто сохранить набор сигналов, содержащий только SIGALRM
, и использовать его повторно.
Тем не менее, на самом деле не имеет значения , происходит ли сигнал во время вызовов sigaddset ()
или sigemptyset ()
- new_set
и old_set
переменные (предположительно) локальные для потока, и критическая секция не входит до тех пор, пока не вернется sigprocmask ()
.
Вы обнаружите, что sigemptyset ()
и sigaddset ()
в signal.h - это просто макросы или встроенные функции, поэтому они выполняются встроенно в вашем код. Просто используйте переменную стека при их вызове.
Однако почему бы вам не сделать это в разделе однопоточного запуска вашего кода? Я также сомневаюсь, что вызов функции sigprocmask будет атомарным. Блокировка сигналов не означает, что ваш код будет бесперебойным.
Кстати, я не уверен, как вы используете ualarm, но если вы не улавливаете или не игнорируете SIGALARM при первом вызове, вы, вероятно, убьете свой процесс.
sigprocmask () - единственная функция, которая переходит на уровень ядра и фактически изменяет статус маскировки сигнала. Другие функции - это просто функции манипуляции для установки маски перед вызовом sigprocmask или передачей набора другой функции, связанной с сигналом.