Unix 为什么';t子进程在收到信号后是否继续运行?

Unix 为什么';t子进程在收到信号后是否继续运行?,unix,process,fork,signals,Unix,Process,Fork,Signals,下面是我的代码。父母分给孩子。子进程暂停,直到父进程向它发送信号,然后它继续运行。 我的问题是为什么子进程不继续 在家长向他发出信号后奔跑。我是否错过了什么或误解了什么 #include<stdio.h> #include<unistd.h> #include<signal.h> void sigusr1( int pidno ) { printf("Catched\n"); } int main() { pid_t pid; sign

下面是我的代码。父母分给孩子。子进程暂停,直到父进程向它发送信号,然后它继续运行。 我的问题是为什么子进程不继续 在家长向他发出信号后奔跑。我是否错过了什么或误解了什么

#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();
}
#包括
#包括
#包括
无效的
sigusr1(内部pidno)
{
printf(“捕获的\n”);
}
int
main()
{
pid_t pid;
信号(SIGUSR1,SIGUSR1);
如果((pid=fork())==0){
暂停();
printf(“Child\n”);
}
kill(pid,SIGUSR1);//父对象向子对象发送信号
暂停();
}
试试这个:

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


void
sigusr1( int pidno )
{
  fprintf(stderr, "Caught\n");
}

int
main()
{
  pid_t pid;

  signal( SIGINT, sigusr1 );
  if( (pid = fork()) == 0 ){
    pause();
    fprintf(stderr, "Child\n");
  }
  else
  {
    fprintf(stderr, "Parent\n");
    kill( pid , SIGINT ); //parent sends signal to child
  }
  pause();
  return 0;
}

以下是在父对象中发生的情况:

  • 叉一个孩子
  • 将SIGUSR1发送给孩子
  • 等待信号

  • 以下是孩子身上发生的事情:

  • 等待信号
  • 打印
    子项
  • 调用
    kill(0,SIGUSR1)
    (0是子对象中
    pid
    的值)。调用进程ID为0的
    kill
    会将信号发送到调用
    kill
    的进程中的每个进程
  • 等待信号
  • 根据父系统调用和子系统调用的执行顺序,程序有几种可能的行为。根据操作系统的确切版本、各种内核参数的微调、系统的加载方式以及随机情况,如果多次运行程序或在调试器下运行程序,您可能会或可能不会观察到不同的行为

    如果父级启动比子级启动快,您可能会看到:

  • 父级将SIGUSR1发送给子级
  • 孩子接收SIGUSR1并打印捕获的
  • 子调用
    暂停
  • 父调用
    暂停
  • 有了这个执行顺序,父对象和子对象都将永远等待(这是一个错误)

    如果子级启动速度比父级快,您可能会看到:

  • 子调用
    暂停
  • 父级将SIGUSR1发送给子级
  • 父调用
    暂停
  • 子项未被阻止并打印被捕获的
  • 儿童打印
    Child
  • 子进程将SIGUSR1发送到进程组
  • 子打印已捕获的
  • 子调用
    暂停
  • 父项被取消阻止并打印被捕获的
  • 父级退出
  • 我认为孩子没有办法退出:它调用
    pause
    两次,虽然它最多可以接收两个信号,但其中一个信号是从自身发送的(来自
    kill(0,SIGUSR1)
    ),另一个是同步发送的,而不是在执行
    pause
    期间

    这个程序可能不是你想写的,但是因为你没有描述预期的行为,所以不可能知道你想写什么。我注意到,您没有遵循分叉程序的常规结构:

    pid = fork();
    if (pid < 0) {
        /*error handling*/
    } else if (pid == 0) {
        /*child code*/
        exit(...); /*Usually, what follows the if is specific to the parent.*/
    }
    
    pid=fork();
    if(pid<0){
    /*错误处理*/
    }否则如果(pid==0){
    /*子代码*/
    exit(…);/*通常,if后面的内容特定于父级*/
    }
    
    谢谢。我复制了你的代码,但它似乎在我的mac上不起作用。我认为原因是暂停运行之前发送了信号。#1错误:如果程序在终端上打印,它将使用行缓冲#2是对的,但我认为不是全部问题。@Gilles-no:打印是缓冲的。缓冲通常是好的,但它可能会对多个进程或多个线程产生意外的结果。是的,原始代码中的kill是主要问题。@Janus Le-“signal()”设置了一个信号处理程序。“kill()”向进程发送信号。很好,信号在“fork()”之前和随后的“pause()”之前被调用。“kill”(即“send signal”)被意外调用了两次(一次在父级,一次在子级),这正是我一开始想要说的。更糟糕的是,孩子(再一次,无意中)发送了一个“0杀”。这是主要问题。第二个问题可能是行缓冲(影响显示的顺序和时间行)。@paulsm4当输出到终端时,stdout是行缓冲或非缓冲的;这是由C语言规定的,更一般地说是C语言规定的(参见§7.19.3.7)。您的引用:“stdout是行缓冲的或无缓冲的”。默认情况下,在几乎所有*nix(包括Linux)的实现(X终端、putty窗口、文本模式帧缓冲等)中,stdio默认值都是“缓冲的”。C99标准究竟与“终端I/O”有什么关系?@14moose标准在输出为终端时默认为行缓冲。在所有C实现上。C标准(我引用了C99,但C89有类似的语言)是相关的,因为这是一个C程序(POSIX通过引用包括了C标准)。
    pid = fork();
    if (pid < 0) {
        /*error handling*/
    } else if (pid == 0) {
        /*child code*/
        exit(...); /*Usually, what follows the if is specific to the parent.*/
    }