linux通过信号进程间通信实例理解

来源:互联网 发布:知无涯者怎么解释 编辑:程序博客网 时间:2024/05/18 06:36

在linux系统编程的学习中,通过信号进行进程简编译是一大重点
本文通过一个实例加强对sigemptyset、sigprocmask的理解

int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);

其中 signum 为收到的信号

其中

struct sigaction{    void    (*sa_handler)(int); //      }      void    (*sa_sigaction)(int, siginfo_t *, void *);//  }  两个函数指针仅有一个有效    sigset_t   sa_mask;   //阻塞信号集         int   sa_flags;  //若sa_flags==0则*sa_handler;有效,若sa_flags==SA_SIGINFO则*sa_sigaction有效    void   (*sa_restorer)(void);//扩展}
其中sigset_t 为一个结构体,信号在int __val[32] 中以掩码储存,有32位二进制数,以对应一位标‘1’来储存对应信号

我们也可以通过

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);//  在进程阻塞信号集里,增加或删除信号
其中int how 有如下三种参数,均针对oldset            SIG_BLOCK   //增加            SIG_UNBLOCK  //删除            SIG_SETMASK  //先清空进程阻塞集号,再增加

值得一提的是信号在信号集中的存储并非简单赋值,而是以掩码的形式储存,2进制数不同位标‘1’表示不同命令的存储。在此并不详谈。

当进程信号集中存在某一信号SIG***时,向该进程发送此信号则会被阻塞,直至sa_flags对应的函数被执行完成为止。
以下为实例方便理解:
实例一:

#include <stdio.h>#include <signal.h>#include <stdlib.h>#include <unistd.h>pid_t i,j;void f(int sig){    if(kill(i,SIGINT)<0)    {        perror("kill fail");    }    if(kill(j,SIGINT)<0)    {        perror("kill fail");    }    wait(i,NULL,0);    wait(j,NULL,0);    printf("Parent process exit!\n");    exit(0);}void f_1(int sig){    printf("Child process 1 is killed by parent!\n");}void f_2(int sig){    printf("Child process 2 is killed by parent!\n");}int main(){    i = fork();    if(i<0)    {        perror("fork fail");        return -1;    }    else if(i==0)    {        signal(SIGINT,f_1);        pause();    }    else if(i>0)    {        j = fork();        if(j<0)        {            perror("fork fail");            return -1;        }        if(j==0)        {            signal(SIGINT,f_2);//收到SIGINT信号则执行f_2动作            pause();        }        if(j>0)        {            signal(SIGINT,f);            pause();        }    }}

实例二:

#include<stdio.h>#include<signal.h>#include<stdlib.h>int output(sigset_t set){    printf("set.val[0]=%x\n",(int)set.__val[0]);}void handler(int sig){    int i;    sigset_t sysset;    printf("\n nin hadler sig=%d\n",sig);    sigprocmask(SIG_SETMASK,NULL,&sysset);    output(sysset);    printf("return\n");}int main(){    struct sigaction act;    sigset_t set,sysset,newset;//自定义信号集合    sigemptyset(&set);    sigemptyset(&newset);//清空    sigaddset(&set,SIGUSR1);//向进程阻塞信号集中发送信号SIGUSR1    sigaddset(&newset,SIGUSR2);    printf("\nadd sigusr1,the value of set");    output(set);//测试    printf("\nadd sigusr2,the value of newset");    output(newset);    printf("\nafter set proc block set ,and then read to sysset\n");    sigprocmask(SIG_SETMASK,&set,NULL);    //将系统阻塞信号集清空,然后拷贝信号集set的内容到系统阻塞信号集中;    sigprocmask(SIG_SETMASK,NULL,&sysset);    //将信号集sysset中的内容清空,然后拷贝系统阻塞信号集中的内容到sysset    printf("system mask is:\n");    output(sysset);//测试,此时系统阻塞信号集的内容为SIGUSR1    printf("set mask is:\n");    output(set);    printf("install sigalrm,and the act.sammask is newset(siguser2)\n");    act.sa_handler=handler;//在另一终端中输入kill -SIGUSR1 [该进程pid] 并不会立刻执行该信号相应动作,直到handler函数执行完毕    act.sa_flags=0;    act.sa_mask=newset;    sigaction(SIGALRM,&act,NULL);//pause中断进程,直至收到“SIGALRM”信号重新激活,运行act所包含的动作。    pause();    printf("after exec isr\n");    sigemptyset(&sysset);//清空sysset    sigprocmask(SIG_SETMASK,NULL,&sysset);    output(sysset);}
0 0