设置信号信号处理函数void (*signal (int signo ,void (*fun)(int )))(int)

来源:互联网 发布:power point for mac 编辑:程序博客网 时间:2024/05/16 05:51
设置信号信号处理函数void (*signal (int signo ,void (*fun)(int )))(int)
一个进程收到信号时需要跳转到信号处理函数的代码处执行。系统为每个信号提供给了多种默认的处理方式。
linux允许用户提供自己的信号处理函数,使用signal函数将处理函数加载,并且通知系统.
函数原型:
#include<signal.h>
void (*signal (int signo ,void (*fun)(int )))(int)

函数原型各参数详细解释
(一)signal函数的第一个参数是需要加载处理的信号编号,例如
SIGKILL等,该编号是一个宏,其本质是一个整数,定义在signal.h文件中
(二)第二个参数是一个函数指针,这个函数捕捉到第一个函数指定的信号,并对其进行处理,该参数可以是以下三个值中的一个
1)SIG_IGN:表示忽略该信号,即捕捉到信号后不做任何处理,该宏定义在signal.h文件中
#define SIG_IGN ((void *)(*)())1
2)SIG_DFL表示使用默认的信号处理方式,这样可以对此信号恢复系统的默认处理方式,该宏定义在signal.h文件中
#define SIG_DFL ((void *)(*)())0
3)其他已定义的函数指针:表示使用用户自己的处理函数处理此信号,
该信号成为信号处理函数,信号处理函数的原型为:void handler(int);
signal函数的返回值也是一个函数指针,这个函数指向上一次的信号处理程序,因此这个函数和signal的第二个参数所表示的的参数原型一致
,如果出错,signal函数返回SIG_ERR ,该宏定义在signal.h文件中

#define SIG_ERR (void (*)())-1

信号是异步的通信方式,其到来由系统通知应用程序,所以信号处理函数是由系统调用的,其参数表示当前所捕捉到的信号的编号,也就是说该参数其实和signal的第一个参数signal是等效的。这样的好处是多余
的多个信号可以共用一个处理程序,处理程序内部的流程只需要根据参数来判断即可了。
信号处理函数如下:
void handler( int signo )
 {
   switch(signo)
    {
     case SIGUSR1:
           ......
     case SIGUSR2:
           ......
     ......
    case SIGUSRn:
           ......
                                         
    }
 }

下面的程序展示了父子进程使用SIGUSR1和SIGUSR2进行通信
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
void handler( int signo )
 {
   switch(signo)
    {
     case SIGUSR1:
              printf("parent :catch SIGUSR1\n");break;
     case SIGUSR2:
              printf("child :catch SIGUSR2\n");break;
     default :
          printf("should not be here\n");break;
                                         
    }
    return  ;
 }
 
 int main( void )
  {
   pid_t  ppid, cpid ;
   
    /*为两个进程设置信号处理函数*/
    if( signal(SIGUSR1, handler)== SIG_ERR)//设置出错
     {
       perror("can`t set handle for SIGUSR1");
       exit(1);
     }
     
   if( signal(SIGUSR2, handler)== SIG_ERR)//设置出错
     {
       perror("can`t set handle for SIGUSR2");
       exit(1);
     }
  
  ppid = getpid();//得到父进程id
  
  if((cpid = fork() )< 0 )//创建子进程
    {
      perror("fail to fork");
      exit(1);
    }
  else if(cpid == 0)
    {//子进程向父进程发送SIGUSR1信号
     if(kill(ppid,SIGUSR1)== -1)
      {
        perror("fail to send signal");
        exit(1);
      }
      while(1);//死循环,等待父进程的信号
    }
   else 
     {
       sleep(1);//休眠,保证子进程先运行,并且发送SIGUSR1信号
       //向子进程发送SIGUSR2信号
       if(kill(cpid,SIGUSR2) == -1)
      {
        perror("fail to send signal");
        exit(1);
      }
      
      printf("kill child\n");//输出提示信息
      
      if(kill(cpid,SIGKILL)== -1)//发送SIGKILL信号杀死子进程
      {
        perror("fail to send signal");
        exit(1);
      }
      if(wait(NULL) == -1 )//回收子进程状态,避免僵尸进程
       {
         perror("fail to wait");
         exit(1);
       }
     }
  
   return 0;
  }
 
原创粉丝点击