信号发送 & sigqueue、sigaction

sigqueue:给指定pid的进程发送信号sig,并且携带数据(数据存放在value参数中)

int sigqueue(pid_t pid, int sig, const union sigval value);
                                          用于携带数据
union sigval {   
   int   sival_int;
   void *sival_ptr;
};

使用sigaction处理sigqueue发来的信号

[1] 定义sigaction的信号处理函数,用来接收sigqueue函数发来的数据:接收的数据存放在siginfo_t结构体的si_value变量

void handler(int signum, struct siginfo_t* s_t, void* ptr)
{   
	 printf("         param = %d\n",s_t->si_int);     
}   	

详细介绍:struct siginfo_t 结构体(包含了信号产生原因的有关信息)

struct siginfo_t{
  int   si_signo; // 接收到的信号
  int   si_errno; // if 非0,errno value from <errno.h>
  int   si_code;  // 补充信息(取决于signal)
  pid_t si_pid;   // sending process ID
  uid_t si_uid;   // sending process real user ID
  void *si_addr;  // address that caused the fault
  int   si_status;// exit value or signal number

  union sigval si_value; // application-specific value
}

union sigval si_value{
  int   sival_int;  //传递整数值
  void* sival_ptr;  //传递一个指针值
}

[2] 定义并初始化sigaction的第二个参数act变量

struct sigaction act;        
sigemptyset(&act.sa_mask); // 清空信号屏蔽集合           
act.sa_flags=SA_SIGINFO;   // 设置SA_SIGINFO标志
act.sa_sigaction=handler;  // 回调函数  

[3] 调用sigaction函数注册XXX信号:sigaction(XXX,&act, NULL);
[4] 给指定进程,通过sigqueue函数发送[带有数据的XXX信号]

union sigval value;
value.sival_int=24; //数据被s_t->si_int接收到
sigqueue(pid,XXX,value);

示例代码

程序功能
1.父进程创建子进程1和子进程2
2.子进程1给子进程2发送可靠信号,并传送额外数据(子进程1的pid*2)
3.子进程2接收到可靠信号的值后,并将接收的值发送给父进程,父进程把接收的值打印
程序实现技巧
1.在父进程中可以通过 [缓存数组] 得到所有子进程的进程ID
2.[缓存数组]中的数据,在父进程/子进程1/子进程2中是相互独立的

step1:子进程1要发送数据给子进程2(但是子进程1无法知道子进程2的进程ID),因此需要父进程先将子进程2的PID发送给子进程1
step2:子进程1接收到父进程发来的[数据(子进程2的PID)]后,在信号处理函数中,修改[缓存数组]
step3:子进程1将[数据(子进程1的PID*2)]发送给子进程2
step4:子进程2获得数据后,修改自己的message
setp5:子进程将message发送给父进程
step6:父进程接收到message后,打印接收到的message

pid_t pidArray[10];
pid_t message;     
       
void handler(int signum, siginfo_t* s_t, void *ptr){   
  if(signum==SIGRTMIN+1){      
    printf("  process1 recv SIGRTMIN+1,value=%d\n",s_t->si_value.sival_int);   
    pidArray[1]=s_t->si_value.sival_int; //step2:子进程1获得子进程2的进程ID后,修改自己的缓存数组pidArray[1]
  }    
  else if(signum==SIGRTMIN+2){ 
    printf("  process2 recv SIGRTMIN+2,value=%d\n",s_t->si_value.sival_int);   
    message=s_t->si_value.sival_int; //step4:子进程2获得数据后,修改自己的message     
  }    
  else if(signum==SIGRTMIN+3){ 
    printf("  parent recv SIGRTMIN+3,value=%d\n",s_t->si_value.sival_int); //step6:父进程接收到message后,打印接收到的message      
  }    
}    
int main(){        
  struct sigaction act;        
  act.sa_flags=SA_SIGINFO;     
  act.sa_sigaction=handler;    
  sigemptyset(&act.sa_mask);   
  sigaction(SIGRTMIN+1,&act,NULL);         
  sigaction(SIGRTMIN+2,&act,NULL);         
  sigaction(SIGRTMIN+3,&act,NULL);         
       
  int thread_num=2;
  pid_t pid;       
  int i;           
  for(i=0;i<thread_num;i++){   
    pidArray[i]=pid=fork();    
       
    if(pid==0){    
      break;       
    }  
  }    
  if(i==0){ //process1         
    sleep(5);      
       
    union sigval value;        
    value.sival_int=getpid()*2;
    printf("process1 ---> process2:[ SIGRTMIN+2: message]\n");     
    sigqueue(pidArray[1],SIGRTMIN+2,value); //step3:子进程1将[数据(子进程1的进程ID*2)]发送给子进程2           
  }    
  if(i==1){ //process2         
    sleep(10);     
       
    union sigval value;        
    value.sival_int=message;   
    printf("process2 ---> parent:[ SIGRTMIN+3: message]\n");       
    sigqueue(getppid(),SIGRTMIN+3,value); //setp5:子进程将message发送给父进程  
  }  
  if(i==thread_num){ //parent process      
    union sigval value;        
    value.sival_int=pidArray[1];           
       
    printf("parent ---> process1:[ SIGRTMIN+1:pidArray[1] ]\n");   
    sigqueue(pidArray[0],SIGRTMIN+1,value);  // step1:父进程将子进程2的进程ID发送给子进程1     
       
    //wait child process       
    int status;    
    pid_t ret;     
    while((ret=waitpid(-1,&status,WNOHANG))!=-1){      
      if(ret==0)   
        continue;  
      printf("wait %d pid",ret);           
      if(WIFEXITED(status))    
        printf("exit,status=%d\n",WEXITSTATUS(status));
      else if(WIFSIGNALED(status))         
        printf("signal,status=%d\n",WTERMSIG(status)); 
    }  
  }    
  return 0;        
} 

[gjw@localhost homework]$ ./work 
parent ---> process1:[ SIGRTMIN+1:pidArray[1] ]
  process1 recv SIGRTMIN+1,value=36534
process1 ---> process2:[ SIGRTMIN+2: message]
  process2 recv SIGRTMIN+2,value=73066
process2 ---> parent:[ SIGRTMIN+3: message]
  parent recv SIGRTMIN+3,value=73066
wait 36533 pidexit,status=0
wait 36534 pidexit,status=0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值