Linux环境编程之信号处理(一)

来源:互联网 发布:qq语音录制软件 编辑:程序博客网 时间:2024/05/19 04:27

        已经有差不多一年没有使用 《unix环境高级编程》中的知识了,现在抽个时间大概的复习下《unix环境高级编程》,也顺便记录下,方便以后再复习使用;


信号简介

        1、信号是软件中断,提供的是一种处理异步事件的方法;
        2、不存在编号为0的信号,在kill函数中对信号0有特殊应用;
        3、对信号的处理方法有三种:
              a、忽略信号,也就是不做任何处理,SIGKILL/SIGSTOP(即:9/19号信号)不能被忽略;

              b、捕捉信号,也就是调用用户开始设计好的信号处理函数去处理;9/19号信号不能被捕捉;

              c、系统默认,不做处理,也不设置默认,调用系统定义的处理该信号的方法去执行;(绝大部分默认为终止该进程)

        4、可以调用命令:kill -l  来查看系统支持的信号;2号信号 ---- ctrl+c ---- SIGINT;20号信号 ---- ctrl+z ---- SIGTSTP;


signal函数

        signal函数原型:void  (*signal(int signo, void (*func)(int) ) ) (int);

        该函数的功能:当信号signo 发生时,调用 func 函数去处理;其实就是对signo的信号进行绑定;

        函数分析:

        void (*func)(int) 这是一个函数指针,其实就是表示一个函数的入口地址,当信号发生时,跳转到该入口地址去执行;

        signo 是信号的编号,指定某个信号;

        所以:signal的函数为   signal(int signo,  void  (*func)(int)) ;我们一般使用的时候也是这样用的,例如:signal(SIGINT, faction);对SIGINT信号进行绑定;

        那为什么上面的原型不一样呢,那是因为上面的原型是包括了返回值,而signal的返回值是一个函数指针,带有int参数,返回值为空  的函数指针;其实返回的函数指针就是该信号前一个绑定的处理函数指针;

        看下面的程序,能够很好的理解signal函数:

 #include<signal.h> #include<stdio.h>  void sigFaction(int signo)// 第一次为SIGINT信号绑定的处理函数 {     if (signo == 100) // 这里signo不是代表信号,是为了测试signal返回函数指针用的         printf("signal ret!\n");          if (signo == SIGINT)// 这里是测试SIGINT信号处理方法         printf("ctrl + c\n"); }  void test(int signo)// 第二次为SIGINT信号绑定的处理函数 {     if (signo == SIGINT)         printf("test\n"); }  int main(void) {     if (SIG_ERR == signal(SIGINT, sigFaction) )// 第一次开始为SIGINT信号进行绑定         printf("sigint error!\n");// 出错打印      sleep(10);// 睡眠会,期间发生ctrl+c 则会调用上面绑定的sigFaction函数进行处理      signal(SIGINT, test)(100);// 这里利用signal()函数返回上一次绑定的函数指针,进行调用sigFaction()函数,传入的参数为100;同时为SIGINT绑定test处理函数      while(1) pause();// 为了等待信号发生,避免进程终止      return 0; }

        代码分析:

        设计这个代码主要是分析signal()函数原型,第一次为信号SIGINT绑定了sigFaction()函数,当ctrl+c发生时,会调用sigFaction()函数来进行处理的;

        然后执行 signal(SIGINT, test)(100); 因为signal()函数返回的是上一次为该信号绑定的处理函数指针,所以这里顺便调用下上一次绑定处理函数,传入参数为 100,所以在sigFaction()函数中会打印相应的信息;

        同时,这里也会为SIGINT信号进行第二次绑定test处理函数。那么当ctrl + c再次发生时,就会调用test()函数来进行处理了;

运行结果:

        

        注意:在调试信号程序时,建议还是先看看http://blog.csdn.net/yuzhihui_no1/article/details/44564963,这样会很方便调试;


简化理解

        如果上面对signal原型分析的还不能理解的话可以试试用typedef来简化下;

        根据上面代码:typedef  void sigPoint(int);  这里把  void xxx(int)类型的函数统一为  sigPoint函数; 

        则:void  (*signal(int signo, void (*func)(int) ) ) (int);  ====  sigPoint  *signal(int, sigPoint*);


信号系统处理函数

        上面已经说过,对信号响应有三种情况;第一、忽略该信号;第二、捕捉该信号;第三、执行系统默认动作;第二种 捕捉该信号,上面已经讲过,当捕捉到该信号后,执行用户最开始设置好的处理函数;
        第一种,忽略该信号,则是把 1强转为函数 SIG_IGN:#define SIG_IGN (void (*)())1;
        第三种,执行系统默认动作,则是把0强转为函数SIG_DFL:#define SIG_DFL (void (*)())0
        
        还有一个绑定出错的函数 SIG_ERR:#define SIG_ERR (void (*)()) -1;

         

        转载请注明作者和原文出处,原文地址:http://blog.csdn.net/yuzhihui_no1/article/details/44748585

        若有不正确之处,望大家指正,共同学习!谢谢!!!

 
0 0
原创粉丝点击