Неоднозначное поведение системного вызова kill в C
Я сделал эту программу, и вывод пока не имеет особого смысла для меня. Может кто-нибудь объяснить, что происходит?
void handler1a(int x){
printf("A\n");
}
int main(){
signal(SIGUSR1, handler1a);
int p = fork();
if(p==0)
{
sleep(5);
printf("L \n");
}
else
{
kill(0,SIGUSR1);
kill(0,SIGUSR1);
kill(0,SIGUSR1);
//kill(0,SIGUSR1);
wait(NULL);
}
}
С 3 сигналами убийства мой выход - 5А и 1л. С 2 сигналами уничтожения выход - 4A и 1L. С 4 сигналами убивания, выход - 6А и 1л. Кажется, что до 2 сигналов уничтожения, и родительский, и дочерний процессы используют мой пользовательский обработчик, но каким-то образом один из них не использует обработчик или не получает сигнал уничтожения после получения сигнала, который он уже дважды (это объясняет, почему только один A печатается, когда я добавляю еще один системный вызов kill после 2 системных вызовов kill).
2 ответа
Сигналы не поставлены в очередь. Таким образом, если вы отправляете один и тот же сигнал процессу несколько раз, он может обрабатываться любое количество раз от 1 до количества отправлений сигнала.
Или, другими словами, для каждой комбинации процесса и сигнала сигнал может находиться в сигнальном состоянии. Если вы отправляете сигнал процессу, когда этот процесс уже находится в сигнальном состоянии для этого сигнала, ничего не происходит.
Процесс не может иметь двух ожидающих сигналов SIGUSR1. Либо SIGUSR1 ожидает, либо нет.
Вот kill
вызывается родительским процессом P с 0
в качестве значения pid, которое означает, что все процессы в его группе (самP, а также дочерний элемент C) получат сигнал, и для его обработки будет использован тот же пользовательский обработчик сигнала.
Если вы отправляете в процесс C несколько сигналов одного типа (SIGUSR1
здесь), они не будут поставлены в очередь, потому что этот сигнал будет заблокирован, пока не будет обработан первый полученный, и они будут отброшены.
Только когда обработчик сигнала для C возвращается, C готов снова обработать сигнал. Это объясняет, почему в выводе из вызова C обработчика меньше "A".
Вы можете увидеть, какой процесс вызвал обработчик, добавив printf("A %d\n", getpid())
внутри обработчика.