Использование sigprocmask для реализации блокировок - PullRequest
1 голос
/ 18 мая 2010

Я реализую пользовательские потоки в ядре 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);

Что хорошо, за исключением того, что это кажется многословным. Разве нет лучшего способа сделать это?

Ответы [ 3 ]

1 голос
/ 18 мая 2010

Как указывает WhirlWind , функции набора сигналов довольно легковесны и могут даже быть реализованы в виде макросов; и вы также можете просто хранить набор сигналов, который содержит только SIGALRM, и использовать его повторно.

Несмотря на это, на самом деле не имеет значения , если сигнал происходит во время вызовов sigaddset() или sigemptyset() - переменные new_set и old_set являются (предположительно) локальными для потоков, и критический раздел не вводится до тех пор, пока не вернется sigprocmask().

1 голос
/ 18 мая 2010

Вы обнаружите, что sigemptyset() и sigaddset() в signal.h являются просто макросами или встроенными функциями, поэтому они выполняются встроенными в вашем коде. Просто используйте переменную стека при вызове их.

Однако, почему бы вам не сделать это в однопоточном разделе запуска вашего кода? Я также сомневаюсь, что вызов функции sigprocmask будет атомарным. Блокировка сигналов не означает, что ваш код будет бесперебойным.

Кстати, я не уверен, как вы используете ualarm, но если вы не перехватываете или не игнорируете SIGALARM при первом вызове, вы, вероятно, убьете свой процесс.

0 голосов
/ 23 мая 2010

sigprocmask () - единственная функция, которая переходит на уровень ядра и фактически изменяет статус маскирования сигнала. Другие функции - это просто функции манипуляции для установки маски перед вызовом sigprocmask или передачи набора в другую функцию, связанную с сигналом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...