Linux 进程间通信 信号

来源:互联网 发布:微博个性域名二次更改 编辑:程序博客网 时间:2024/03/29 08:06

信号

信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。

信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。

进程可以通过三种方式来响应一个信号:

(1)忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及 SIGSTOP;

(2)捕捉信号。定义信号处理函数,当信号发生时,执行相应的处理函数;

(3)执行缺省操作;


信号发送及处理

sigreceive.c

#include <signal.h>#include <sys/types.h>#include <unistd.h>void new_op(int,siginfo_t*,void*);int main(int argc,char**argv){    struct sigaction act;    int sig=atoi(argv[1]);    sigemptyset(&act.sa_mask);    act.sa_flags=SA_SIGINFO;    act.sa_sigaction=new_op;    if(sigaction(sig,&act,NULL)<0){        printf("install signal error\n");    }    int count=0;    while(1){        sleep(1);        printf("wait for signal:%d\n",++count);        if(count>10)break;    }    return 0;}void new_op(int signum,siginfo_t* info,void* myact){    printf("receive signal:%d\n",signum);    sleep(5);}
后台运行 sigreceive signo &,可获得该进程的 ID,假设为 pid,然后再另一终端上运行 kill -s signo pid 验证信号的发送接收及处理.

信号传递附加信息

1.向进程本身发送信号,并传递指针参数

#include <signal.h>#include <sys/types.h>#include <unistd.h>void new_op(int sig,siginfo_t* info,void* act){    int i=0;    for(i=0;i<10;i++){        printf("%c,",(*((char*)((*info).si_ptr)++)));    }    printf("\nhandle sig:%d\n",sig);}int main(int argc,char** argv){    struct sigaction act;    union sigval mysigval;    int i;    int sig;    pid_t pid=getpid();    char data[10]={'2','2','2','2','2'};    mysigval.sival_ptr=data;    sig=atoi(argv[1]);    sigemptyset(&act.sa_mask);    act.sa_sigaction=new_op;    act.sa_flags=SA_SIGINFO;    if(sigaction(sig,&act,NULL)<0){        printf("install sig error\n");    }   // int count=0;//    while(1){//        sleep(1);        printf("wait for sig\n");        sigqueue(pid,sig,mysigval);    //    if(count++>10)break;  //  }    return 0;}

2、 不同进程间传递整型参数:把 1 中的信号发送和接收放在两个程序中,并且在发送过程中传递整型参

sig_send.c

#include <unistd.h>#include <sys/types.h>#include <signal.h>int main(int argc,char** argv){    union sigval sigv;   // char** data={"First","Second"};//    char** data = (char**)malloc(sizeof(char* )*2);  //  data[0] = "first";   // data[1] ="second";//    char* data[2]={"First","Second"};//    sigv.sival_ptr=data;    char data[2]={'1','1'};//    sigv.sival_ptr=data;    sigv.sival_int=9;    pid_t pid=atoi(argv[1]);    int sig=atoi(argv[2]);        sigqueue(pid,sig,sigv);    printf("Message has been send\n");    sleep(7);    printf("Send dead\n");    return 0;}

sig_rev.c

#include <signal.h>#include <sys/types.h>#include <unistd.h>void op(int sig,siginfo_t *info,void* sigact){    printf("inside op\n");    int count=0;//    while((*info).si_ptr!=NULL){        count++;       // char* p=*((char**)((*info).si_ptr)+1);       // char* p=((char*)((*info).si_ptr));       // printf("op %c\n",*p);//        printf("%c,",(*((char*)((*info).si_ptr))));    printf("op value:%d\n",info->si_int);  //  }}int main(int argc,char** argv){    int sig=atoi(argv[1]);    pid_t pid=getpid();    printf("Rev pid:%d\n",pid);    struct sigaction act;    sigemptyset(&act.sa_mask);    act.sa_flags=SA_SIGINFO;    act.sa_sigaction=op;    if(sigaction(sig,&act,NULL)<0){        printf("install sig error\n");    }    int count=0;    while(1){        sleep(1);        count++;        printf("wait for sig %d\n",count);        if(count>30)break;    }    return 0;}
注:实例 2 的两个例子侧重点在于用信号来传递信息,目前关于在 linux 下通过信号传递信息的实例非常
少,倒是 Unix 下有一些,但传递的基本上都是关于传递一个整数,传递指针的我还没看到。我一直没有实
现不同进程间的指针传递(实际上更有意义),也许在实现方法上存在问题吧

参考郑彦兴《Linux进程通信》

原创粉丝点击