首页 > 其他 > 详细

signal 函数只能接受一次信号? The naughty signal function

时间:2014-03-31 14:17:53      阅读:676      评论:0      收藏:0      [点我收藏+]

The naughty signal function



signal 函数的prototype:
       #include <signal.h>
       typedef void (*sighandler_t)(int);
       sighandler_t signal(int signum, sighandler_t handler);



在练习是时候发现一个问题: 学APUE都应该看过这个demo
#include"apue.h"
#include"stdio.h"
#include"myerr.h"


static void sig_usr(int);


int main()
{
        if(signal(SIGUSR1,sig_usr) == SIG_ERR)
        {
                err_sys("signal error\n");
        }


        if(signal(SIGUSR2,sig_usr) == SIG_ERR)
        {
                err_sys("can‘t catch SIGUSR2");
        }


        for(;;)
        {
                pause();
        }


        return 0;
}


static void sig_usr(int signo)
{
        if(signo == SIGUSR1)
        {
                printf("received SIGUSR1\n");
        }
        else if(signo == SIGUSR2)
        {
                printf("received SIGUSR2\n");
        }
        else
        {
                err_dump("received signal %d\n",signo);
        }
}
我觉得还是先引出问题的比较好。
so ,test result:
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ gcc ./pro_10_2.c -g -o ./a.out
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ./a.out &
[1] 3310
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3310
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ received SIGUSR1
kill -USR2 3310
received SIGUSR2
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ps
  PID TTY          TIME CMD
 3187 pts/0    00:00:00 bash
 3310 pts/0    00:00:00 a.out
 3311 pts/0    00:00:00 ps
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ps
  PID TTY          TIME CMD
 3187 pts/0    00:00:00 bash
 3310 pts/0    00:00:00 a.out
 3312 pts/0    00:00:00 ps
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3310
[1]+  User defined signal 1   ./a.out
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ps
  PID TTY          TIME CMD
 3187 pts/0    00:00:00 bash
 3313 pts/0    00:00:00 ps


The question is coming!

为嘛我发送一次信号,ps,程序还在跑,没事,我发送第二次不同的信号SIGUSR2,没是,程序还在跑,
为嘛我发送第二次相同的信号SIGUSR1 程序就给死掉了。。。

为这个问题,各种请教,各种无果

最后还是自己想通了。。。



我们像一个侦探一样来慢慢剖析这段code,这是个非常享受,有意思的过程。Just enjoy it。

首先
for(;;)
{
        pause();
}

这就是一个死循环,然后里面调用了pause函数,可以把当前进程挂起。所谓的suspended
如果不知道神马叫做挂起:=_=

挂起是指在操作系统进程管理将前台的进程暂停并转入后台的动作。将进程挂起可以让用户在前台执行其他的进程。挂起的进程通常释放除CPU以外已经占有的系统资源,如内存等。

在需要时用户可以恢复进程的运行,将被挂起的进程从后台转入前台,并从暂停处开始继续运行。

                                                                                            -- wikipedia
 
 
这个时候如果把程序放在background group里面运行,通过shell 的kill 给个信号,可以触发signal handler来处理这个signal。于是就有:
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ./a.out &
[1] 3310
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3310
jasonleaster@ubuntu:/Ad_Pro_in_Unix/chapter_10$ received SIGUSR1


但是为什么送第二次相同的信号就死掉了呢?

原因在这里

        if(signal(SIGUSR1,sig_usr) == SIG_ERR)
        {
                err_sys("signal error\n");
        }


        if(signal(SIGUSR2,sig_usr) == SIG_ERR)
        {
                err_sys("can‘t catch SIGUSR2");
        }
这个就是创建signal handler函数的语句。

我们必须非常仔细的注意,这里的signal handler的declaration:

static void sig_usr(int);

static的作用并不是把函数放在 静态内存区域,而是限定函数的作用域。signal handler是在stack上面的!

这才是问题的关键!这么以来,上面的code就只将sig_usr 载入了两次,一次给SIGUSR 1,一次给SIGUSR2

触发signal handler之后是会被弹栈的!这个时候signal handler就木有了!

之后如果继续向signal handler 发送信号就会触发default behaviour for SIGUSR1 and SIGUSR2.

他们的default behaviour就是termination 。。。so 程序挂掉。




if(signal(SIGUSR1,sig_usr) == SIG_ERR)
{
        err_sys("signal error\n");
}


if(signal(SIGUSR2,sig_usr) == SIG_ERR)
{
       err_sys("can‘t catch SIGUSR2");
}
这部分就是创建信号处理函数的signal handler


用我自己写的demo来印证我的explanation
/*********************************************************************
code writer : EOF
code date : 2014.03.31
e-mail : jasonleaster@gmail.com
code purpose :
        I would like to share my code with someone like me.
Just a demo for signal function. The signal would be loaded
to stack.Load once, pop once.


**********************************************************************/
#include"apue.h"
#include"stdio.h"
#include"myerr.h"


static void sig_usr(int);


int main()
{
        int temp = 0;


        if(signal(SIGUSR1,sig_usr) == SIG_ERR)
        {
                err_sys("signal error\n");
        }


        if(signal(SIGUSR2,sig_usr) == SIG_ERR)
        {
                err_sys("can‘t catch SIGUSR2");
        }


        for(temp = 0;1;temp++)
        {
                pause();


                if(temp < 1)
                {
                        if(signal(SIGUSR1,sig_usr) == SIG_ERR)
                        {
                                err_sys("signal error\n");
                        }


                        if(signal(SIGUSR2,sig_usr) == SIG_ERR)
                        {
                                err_sys("can‘t catch SIGUSR2");
                        }
                }
        }


        return 0;
}

static void sig_usr(int signo)
{
        if(signo == SIGUSR1)
        {
                printf("received SIGUSR1\n");
        }
        else if(signo == SIGUSR2)
        {
                printf("received SIGUSR2\n");
        }
        else
        {
                err_dump("received signal %d\n",signo);
        }
}



这个时候我载入四次sigusr 我发送超过两次SIGUSR1才会挂掉
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_10$ ./a.out &
[1] 3372
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3372
received SIGUSR1
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3372
received SIGUSR1
liuzjian@ubuntu:/Ad_Pro_in_Unix/chapter_10$ kill -USR1 3372
[1]+  User defined signal 1   ./a.out




That‘s all .  Thank you。 

I wish this blog would help you if you come across the problem.

bubuko.com,布布扣






signal 函数只能接受一次信号? The naughty signal function,布布扣,bubuko.com

signal 函数只能接受一次信号? The naughty signal function

原文:http://blog.csdn.net/cinmyheart/article/details/22655659

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!