unix - 为什么子进程收到信号后不继续运行?

标签 unix process fork signals

以下是我的代码。 parent fork 。 child 暂停,直到 parent 向它发送信号,然后它继续运行。 我的问题是为什么子进程不继续 追着 parent 向他发出信号。我错过或误解了什么吗?

#include<stdio.h>
#include<unistd.h>
#include<signal.h>


void 
sigusr1( int pidno )
{
  printf("Catched\n");
}

int 
main()
{
  pid_t pid;

  signal( SIGUSR1, sigusr1 );
  if( (pid = fork()) == 0 ){
    pause();
  printf("Child\n"); 
  }

  kill( pid , SIGUSR1 ); //parent sends signal to child 
  pause();
}

最佳答案

这是在父级中发生的事情:

  1. 叉一个 child 。
  2. 将 SIGUSR1 发送给 child 。
  3. 等待信号。

这是 child 身上发生的事情:

  1. 等待信号。
  2. 打印 child
  3. 调用kill(0, SIGUSR1)(0 是子进程中pid 的值)。使用进程 ID 0 调用 kill 会将信号发送到 process group 中的每个进程调用 kill 的进程。
  4. 等待信号。

您的程序有几种可能的行为,具体取决于父系统调用和子系统调用的执行顺序。根据操作系统的确切版本、各种内核参数的微调、系统的负载情况以及随机机会,如果多次运行程序或在特定条件下运行程序,您可能会或可能不会观察到不同的行为调试器。

如果父进程比子进程启动得快,你可能会看到:

  1. parent 将 SIGUSR1 发送给 child 。
  2. child 收到 SIGUSR1 并打印 Catched
  3. child 叫暂停
  4. 家长调用暂停

按照这个执行顺序,父子双方都将永远等待(这是一个 deadlock )。

如果 child 开始的速度比 parent 快,您可能会看到:

  1. child 叫暂停
  2. parent 将 SIGUSR1 发送给 child 。
  3. 家长调用暂停
  4. child 被解锁并打印Catched
  5. Child 打印Child
  6. 子进程向进程组发送 SIGUSR1。
  7. child 打印 Catched
  8. child 叫暂停
  9. 父级已解锁并打印 Catched
  10. parent 退出。

我不认为 child 有退出的方法:它调用 pause 两次,虽然它最多可以接收两个信号,其中一个是从它自己发送的(一个来自kill(0,SIGUSR1)) 并且那个是同步传递的,而不是在 pause 执行期间。

这个程序可能不是你想要写的,但由于你没有描述预期的行为,所以不可能说出你真正想写的是什么。我确实注意到您没有遵循 fork 程序的通常结构:

pid = fork();
if (pid < 0) {
    /*error handling*/
} else if (pid == 0) {
    /*child code*/
    exit(...); /*Usually, what follows the if is specific to the parent.*/
}

关于unix - 为什么子进程收到信号后不继续运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7546828/

相关文章:

go - 为什么 Go 中的 os.StartProcess 设置子进程组 id 等于子进程 pid

linux - 如何在 bash 中使用函数?

linux - unix 文件系统中软链接(soft link)相互指向的行为?

php - PHP 中的 cURL : curl_exec() or exec ('curl' )?

scala - 从 Scala 中杀死一个挂起的进程

C# 如何从进程中检索代码然后运行它?

c - 4 个子进程之间的管道通信仅在第一次有效

objective-c - Objective C 版本的 unix "finger"命令

c - Linux 内核 task_struct void *stack

c - 如果在 fork() 之后使用 execv() ,子进程是否可以访问管道?