【问题标题】:Ambiguous behaviour of kill system call in CC中kill系统调用的模棱两可的行为
【发布时间】:2019-07-08 07:11:28
【问题描述】:

我已经制作了这个程序,到目前为止的输出对我来说没有多大意义。有人可以解释发生了什么吗?

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 个终止信号,我的输出是 - 5A 和 1L。使用 2 个终止信号,输出为 - 4A 和 1L。有 4 个终止信号,输出为 - 6A 和 1L。似乎多达 2 个终止信号,父进程和子进程都在使用我的自定义处理程序,但不知何故其中一个没有使用该处理程序,或者在收到两次信号后没有收到终止信号(它可以解释为什么只当我在 2 个 kill 系统调用之后添加另一个 kill 系统调用时,会打印一个 A)。

【问题讨论】:

  • 您不能在信号处理程序中安全地调用printf()。每footnote 188 of the C standard:“因此,信号处理程序通常不能调用标准库函数。” POSIX allows you to call async-signal-safe functions 来自信号处理程序,但 printf() 不是异步信号安全的。
  • 最好使用sigaction 而不是signal。当信号发生时,信号处理程序可能会被重置。 POSIX.1 允许这种依赖于实现的行为。

标签: c operating-system signals system-calls signal-handling


【解决方案1】:

信号没有排队。因此,如果您向一个进程多次发送相同的信号,它可能会被处理任意次数,从 1 到您发送信号的次数。

或者,换句话说,对于进程和信号的每种组合,信号都可以处于信号状态。如果您在某个进程已经处于该信号的信号状态时向该进程发送信号,则不会发生任何事情。

一个进程不能有两个未决的 SIGUSR1 信号。 SIGUSR1 处于待处理状态,或者不是。

【讨论】:

    【解决方案2】:

    这里 kill 由父进程 P 调用,0 作为其 pid 值,这意味着其组中的所有进程(P 本身,如以及子 C) 将获得信号,并且将使用相同的自定义信号处理程序来处理它。

    如果您向进程 C 发送多个相同类型的信号(此处为SIGUSR1),它们将不会排队,因为该信号将被阻塞,直到收到的第一个信号被处理,它们将被丢弃。

    只有当 C 的信号处理程序返回时,C 才准备好再次处理该信号。这解释了为什么 C 调用处理程序的输出中的“A”较少。

    您可以通过在处理程序中添加printf("A %d\n", getpid()) 来查看哪个进程调用了处理程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-28
      • 2020-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-17
      • 1970-01-01
      • 2019-09-13
      相关资源
      最近更新 更多