该信号处理程序时会发生什么? [英] What happens during this signal handling program?

查看:100
本文介绍了该信号处理程序时会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

void main ( )
{   int x;
    signal (SIGUSR1, f);
    x= fork ( );
    if (x == -1) exit (1);
    if (x != 0) 
    {   kill (x, SIGUSR1) ;
        sleep (2);
        exit (0);
    }
}
void f ( )
{
    printf ("signal received");
    exit (0);
}

我认为上面的程序询问系统以启动f函数时由父进程接收的SIGUSR1信号(其显示接收信号)。但我不知道这一点,请随时纠正或透露更多的细节。感谢您的帮助!

I think that the program above asks the system to launch the f function ( which displays "signal received" ) when the SIGUSR1 signal is received by the parent process. but I'm not sure about that, please feel free to correct or to give more details. Thank for the help !

推荐答案

有在code一些错误:

There are some mistakes in your code:


  1. 避免调用信号处理程序的printf()功能。 SIGNAL(7) 手册提供的授权功能,美其名曰名单是信号处理内部安全。阅读:

  1. Avoid calling printf( ) function in signal handler. SIGNAL(7) manual provides a list of authorized functions calling them is safe inside signal-handlers. Read:

异步信号安全功能

一个信号处理函数必须非常小心,因为处理
     别处可能在执行某任意点中断
     该方案。 POSIX有安全功能的概念。 如果
     信号中断不安全函数的执行
,然后处理
     调用一个不安全的功能,则程序的行为是
     未定义。

A signal handler function must be very careful, since processing elsewhere may be interrupted at some arbitrary point in the execution of the program. POSIX has the concept of "safe function". If a signal interrupts the execution of an unsafe function, and handler calls an unsafe function, then the behavior of the program is undefined.

使用返回类型的main() INT ;阅读我应该的main()回用C?

  • Use return type of main() int; read "What should main() return in C?"

    X 将为pid_t 。 (过程辨识)。

    现在可以假设你的程序编译和运行(而处理不执行任何其他信号中断):
    我只是缩进你的code和移 F()之前函数定义主要是因为函数声明遗失,也增加了一些意见,你应该阅读:

    Now lets suppose your program compile and run (not interrupted by any other signal while handler executing): I am just indenting your code and shifting f() function definition before main because function declaration is missing, also adding some comments that you should read:

    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <signal.h>
    void f( )
    {
        printf ("signal received\n");
        exit (0);//if child receives signal then child exits from here
    }            // ******* mostly happens
    int main ( )
    {   int x;
        signal (SIGUSR1, f);// First: handler registered
        x = fork ( );       // Second: Child created, now child will execute in
        if (x == -1)        // parallel with parent 
          exit (1);
        if (x != 0) {// parent           
            kill(x, SIGUSR1) ; // Third: sends signal to child
            sleep(2);          // Forth: parent sleep
        }
        return 0; // parent always exits  
        // Child can exits from here **** 
        // if signal sent from parent delayed
    }
    

    的main()功能,寄存器 F()功能SIGUSR1 信号和呼叫后叉()以创建一个新的进程。在运行时为叉()函数返回一个子进程开始与父进程执行中的平行的。结果
    我可以看到你的code,我想你明白,儿童进程的父进程的副本,除了变量值可以从点不同的叉()收益,因此 X 是孩子,父进程不同。我们可以使用从fork返回值来告诉父进程或儿童节目是否正在运行。但是请注意,这不是父母,但实际上,它接收信号 SIGUSR1 子过程。自进程id的值总是 0 中的任何进程。你检查返回值 X =叉()这是新创建的子进程的PID,在 X 0 和父 X!= 0 。因此,信号从父进程发送到子进程。

    In main() function, you registers f() function for SIGUSR1 signal and after that calls fork() to create a new process. In runtime as fork() function returns a child-process starts executing in parallel with parent process.
    As I can see your code, I think that you understands that child-process is copy of parent-process except values of variables can be different from the point fork() returns and hence x is different in child and parent process. We can use the return value from fork to tell whether the program is running in the parent-process or in child. But note that it is not parent but actually the child-process that receives signal SIGUSR1. Value of self process id is always 0 for any process. You checks the return value x = fork() that is pid of newly created child-process, in child-process value of x is 0 and in parent x != 0. Hence signal is sent from parent process to child process.

    您的意见:

    我认为上面的程序要求系统启动 F()功能(它显示接收信号)当 SIGUSR1 信号被父进程收到。

    I think that the program above asks the system to launch the f( ) function ( which displays "signal received") when the SIGUSR1 signal is received by the parent process.

    我有IM pression,你不认为这两个进程并发执行和可以发生,不久后叉()创建有利于儿童过程中,子进程开始执行,并立即终止之前父进程可以将信号发送到子女(或子女进程能够接收信号)。在这种情况下,函数 F()将永远不会在信号处理程序从未打印执行的机会和printf。

    I have impression that you don't consider that both processes execute concurrently and "it can be happen that soon after fork() create a child-process, child-process start executing and immediately terminate before parent-process can send a signal to child (or child-process can receive the signal)". In that case, function f() will never get a chance to execute and printf in signal handler never prints.

    但是,我刚才上面描述的可能性非常低,因为叉需要时间来创建一个新的进程。即使你一次又一次地执行code大部分时间信号从父进程将执行信号处理程序中发送。

    But the possibility of what I have described just above is very low because fork takes time to create a new process. And even if you execute the code again and again most of the times signal sent from the parent process will execute signal-handler.

    code为 XC :正确的方法是设置一个标志,指示信号处理程序执行,然后调用信号处理程序之外的标志值的基础printf函数正如我在所描述的我答案:如何避免在信号处理用printf 以及背后的原因是通过的Jonathan莱弗勒的在他的回答

    Code is x.c: Correct way is set a flag that indicates that signal handler executed and then call printf function on the bases of flag value outside signal-handler as I have described in my answer: How to avoid using printf in a signal handler? And reason behind it explained by Jonathan Leffler in his answer.

    #define _POSIX_SOURCE 
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <signal.h>
    volatile sig_atomic_t flag = 0; //initially flag == 0
    void f(){
        flag = 1; // flag is one if handler executes
    }
    int main(void){   
      pid_t x;
      (void) signal (SIGUSR1, f);
      x = fork();
      if(x == -1) 
        exit(EXIT_FAILURE);
      if (x != 0){// parent 
        kill(x, SIGUSR1);
        sleep(1);
      }
      if(flag)//print only if signal caught and flag == 1
        printf("%s signal received \n", x == 0 ? "Child:" : "Parent:");
      return EXIT_SUCCESS;
    }
    

    现在编译并执行:

    @:~$ gcc -Wall  -pedantic -std=c99  x.c  -o x
    @:~$ ./x
    Child: signal received 
    @:~$ 
    

    通知子进程版画因为家长发送信号给孩子(但父进程并不如打印在父母无信号捕获)。因此,上述code还是类似的行为,因为你渐渐在code。下面我加在我试图证明的过程并发执行结果在执行不同的实例不同(阅读评论)

    Notice child-process prints because parent sends signal to child(but parent process doesn't prints as no signal catch in parent). So behavior of above code still similar as you was getting in your code. Below I have added one more example in which I am trying to demonstrate that 'concurrent execution of processes results different at different instance of execution'(read comments).

    // include header files...
    volatile sig_atomic_t flag = 0;
    void f(){
        flag = 1;
    }
    int main(void){   
      pid_t x;
      (void) signal (SIGUSR1, f);
      (void) signal (SIGUSR2, f); // added one more signal
      x= fork ( );
      if(x == -1) 
        exit(EXIT_FAILURE);
      if (x != 0){// parent 
        kill(x, SIGUSR1);
        while(!flag); // in loop until flag == 0
      }
      if (x == 0){//child 
        kill(getppid(), SIGUSR2); // send signal to parent 
        while(!flag); // in loop until flag == 0
      }//  ^^^^ loop terminates just after signal-handler sets `flag` 
      if(flag)
        printf("%s signal received \n", x == 0 ? "Child:" : "Parent:"); 
      return EXIT_SUCCESS;
    }
    

    在上面code,两个信号被登记在双方父母和孩子的过程。父进程不睡,但忙中while循环,直至信号设置标志。同样儿童过程中有一个循环,打破作为标志信号处理程序变为1。现在编译这个code和反复运行。我经常尝试过的GOT按照我的系统的输出。

    In above code, two signals are registered in both parent and child process. Parent process doesn't sleeps but busy in a while loop until a signal sets flag. Similarly child-process has a loop that breaks as flag becomes 1 in signal-handler. Now compile this code and run repeatedly. I frequently tried an got following output in my system.

    @:~$ gcc -Wall  -pedantic -std=c99  x.c  -o x
    @:~$ ./x
    Child: signal received 
    Parent: signal received 
    @:~$ ./x
    Child: signal received 
    Parent: signal received 
    @:~$ ./x
    Child: signal received  
    Parent: signal received 
    @:~$ ./x
    Parent: signal received   // <------
    @:~$ Child: signal received 
    ./x
    Child: signal received 
    Parent: signal received 
    @:~$ ./x
    Parent: signal received   // <------
    @:~$ Child: signal received 
    
    @:~$ 
    

    注意输出,一种情况是:直到子进程创建父发送信号和while循环,当子进程得到机会执行(取决于CPU调度),它发回信号,家长和父进程之前进入得到机会执行儿童接收信号,并输出消息。但是,这也有时会发生以前孩子的printf打印;家长接收和打印邮件(也就是我用箭头标记)。

    Notice output, one case is: "till child process created parent sent signal and enter in while-loop and when child-process get chance to execute(depends on CPU scheduling) it send back a signal to parents and before parent process get chance to execute child receives signal and prints message". But it also happens sometimes that before child printf print; parent receives and print message (that is I marked using arrow).

    在最后一个例子,我试图表现出儿童的过程中与父母 - 过程和输出并行执行可以不同,如果你不适用并发控制机制。

    In last example I am trying to show child-process executes in parallel with parent- process and output can be differs if you don't applies concurrency control mechanism.

    一些好的资源要了解信号(1)GNU C库:的信号处理
    (2)CERT C编码标准 11。信号(SIG)

    Some good resource To learn signals (1) The GNU C Library: Signal Handling (2) CERT C Coding Standard 11. Signals (SIG).

    这篇关于该信号处理程序时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆