【问题标题】:Parent process still receive signal while being suspended父进程在挂起时仍然收到信号
【发布时间】:2019-06-09 16:26:13
【问题描述】:

我正在研究Linux编程中的进程,有这段代码我看不懂。据我所知,当一个进程被挂起时,它不会收到信号(唤醒它的除外),但是在这段代码中,当父进程运行时,它调用wait,但它仍然打印出计数器,这意味着它收到了 SIGUSR1。谁能解释一下?

我已经知道顺序或者运行是任意的,如果子进程先运行就没有问题,但是如果父进程先运行呢?

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
pid_t pid;
int counter = 0;
int status;
void handler1(int sig){counter ++;
  printf("counter = %d\n", counter);
  fflush(stdout);
  kill(pid, SIGUSR1);
}void handler2(int sig){counter += 3;
  printf("counter = %d\n", counter);
  exit(0);
}
int main() {
  signal(SIGUSR1, handler1);
  if ((pid = fork()) != 0) {
    pid_t p;
    if ((p = wait(&status)) > 0) {
      counter += 2;
      printf("counter = %d\n", counter);
    }
  } else {
    signal(SIGUSR1, handler2);
    kill(getppid(), SIGUSR1);
    while(1) {};
  }
}

我预计程序会暂停,但每次都运行良好。

【问题讨论】:

  • 等待并不意味着被暂停
  • 你能解释一下吗,这里是关于wait的linux手册:The wait() system call suspends execution of the calling thread until one of its children terminates
  • "暂停执行" 在这种情况下与发送SIGSTOP 信号时的"暂停进程"不同。您在这里遇到了语言问题。
  • ^^ 这个。对于wait(),“暂停执行”只是描述了普通的阻塞。该过程仍然是可调度的,因此可以接收信号。它的文档指出它可能会因EINTR 而失败,这一事实清楚地说明了这一点。

标签: c linux signals system


【解决方案1】:

如果进程不忽略它们,它们总是会收到信号 (signal(SIGnum, SIG_IGN);)。

可以通过设置信号掩码来延迟未忽略的信号(例如,使用sigprocmask,取消屏蔽它们然后会导致传递待处理的信号)或者如果进程停止则它们被延迟(使用SIGSTOP/@987654324 @; 向进程发送SIGCONT 会导致传递未决信号)。 (请注意,非实时信号可能会被合并。例如,当信号发送 3 次时,您可能只收到一次信号。)

wait 这样的阻塞调用会阻塞/暂停进程,直到它们完成或直到信号传递中断它们。

屏蔽信号(例如,使用sigprocmask)有时称为阻塞信号(无法交付),但这与阻塞/休眠/暂停进程(阻止它在 CPU 上运行)的阻塞系统调用不同.

【讨论】:

  • Quib​​ble:实现不一定将多个相同类型的信号排队到同一个进程,如果另一个相同类型的信号已经挂起,这可以解释为忽略(新)信号。此外,通过观察wait() 被明确记录为(允许)可以被信号中断,可以改进这个答案。
  • @JohnBollinger:[仅出于完整性考虑]“实现不一定将相同类型的多个信号排入同一进程”他们为SIGCHLDs 所做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多