同一个主机的进程间通信:

  1. 无名管道(PIPE)——适用与任何同主机进程(多亲缘关系进程)——管道是单向的,多进程使用同一管道会产生交叉读写的问题
  2. 有名管道(FIFO)——依赖文件系统,实现不同进程对文件系统下某个文件的访问
  3. 消息队列(Message Queue)——同主机任意多进程间通信——存放的数据量有限,适用与少量数据传递
  4. 共享内存(Share Memory)——同主机任意进程间大量数据通信——数据访问存在竞争问题
  5. 信号(Signal)——同主机进程间同步机制
  6. 信号量(semaphore)——同主机进程间异步机制

网络主机间进程通信:

  1. RPC
  2. 套接口(Socket)

Linux信号是一种进程间异步通信机制,在实现上是软中断。对进程而言,信号的产生是随机的,所以进程无法预先知道信号会不会发送到当前进程,也无法预见什么时候发送到进程

发送信号即进程产生信号并发送给目标进程,当操作系统发送信号到目标进程时成为递送信号,被递送的信号在目标进程被执行成为捕获信号

信号到来时目标进程不执行默认操作而执行自定义代码,称为安装中断(安装信号),在目标进程中设置要执行的自定义代码

产生信号,并发送给目标进程,但此时目标进程以告知操作系统它现在暂时不接受信号,等过一段时间目标进程解除屏蔽之后再接受信号,此时产生并发送给目标进程但被屏蔽的信号成为未决信号,目标进程告知操作系统暂时不接受信号称为屏蔽信号;

若信号被递送到目标进程,但目标进程不处理而至接丢弃,成为忽略信号

在进程屏蔽信号期间其他进程多次发送同一个信号,不可靠信号只有一次未决记录,即屏蔽解除后只执行一次,可靠信号则发送多少次记录多少次,解除后便执行多少次

信号的生命周期:

(1)在目的进程中安装信号(即在目的进程中设置自定义代码)

采用linux系统调用signal(要接收的信号,接收到信号后的处理函数入口),sigaction(要接收的信号,指定欲设置的信号处理方式,存储执行此函数前针对此信号的安装信息)

(2)某进程产生信号,同时设置目的进程(通过进程pid),后由操作系统管理(发送信号

  • 采用linux系统调用kill(目的进程pid,信号值),传递一个信号给指定进程,
  • raise(信号值),传递信号给当前进程,
  • alarm(时间),唤醒进程以及设置定时(在多少时间内发送超时信号SIGALRM给当前进程)
  • ualarm(n内产生超时信号,每隔m重复产生此信号),mn单位为us

(3)信号在目的进程被注册(即将信号值放入进程的未决信号集)

(4)信号在进程中注销

   要在进程执行相应处理程序之前注销进程

(5)信号生命终止

    注销后,目的进程根据进程对信号设置的处理方式暂时终止当前代码的执行,保护上下文、执行信号处理函数(捕获信号),回复到终端位置继续执行

 

信号处理的方法有两种,一种是使用signal函数进行处理即安装信号处理函数,另一种使用信号集函数。 

  • signal(要接收的信号,接收到信号后的处理函数入口)
 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include <signal.h>
 4 
 5 void sig_usr(int sig);
 6 
 7 int main(int argc,char* argv[])
 8 {
 9         int i=0;
10         if(signal(SIGUSR1,sig_usr)==SIG_ERR)//SIGUSR信号到来时执行sig_usr代码的操作
11         {
12                 printf("can't catch SIGUSR1\n");
13                 }
14         if(signal(SIGUSR2,sig_usr)==SIG_ERR)
15         {
16                 printf("can't catch SIGUSR2\n");
17                 }
18         while(1)
19         {
20                 printf("%2d\n",i);
21                 pause();//让进程暂停直到信号出现
22                 i++;
23                 }
24                 return 0;
25         }
26 
27 void sig_usr(int sig)
28 {
29         if(sig==SIGUSR1)
30                 printf("received SIGUSR1\n");
31         else if(sig==SIGUSR2)
32                 printf("received SIGUSR2\n");
33                 else
34                         printf("uncleared signal %d\n",sig);
35         }
signal

[root@sun signal]# ./signal&    //获得进程ID            另一个终端发送信号:
[1] 5572
[root@sun signal]#  0       //并执行./signal              [root@sun signal]# kill -SIGUSR1 5572
received SIGUSR1                          
 1                                    [root@sun signal]#kill -SIGUSR2 5572
received SIGUSR2
 2
函数将返回针对此信号的上一次设置,如果设置多次则返回最近一次设置

 

 

  • 第二种是信号集处理信号:信号集是一个能表示多个信号的数据类型,sigset_t set ,set即一个信号集。

既然是一个集合,就需要对集合进行添加/删除等操作。

  int sigemptyset(sigset_t *set); 将set集合置空
  int sigfillset(sigset_t *set); 将所有信号加入set集合
  int sigaddset(sigset_t *set,int signo); 将signo信号加入到set集合
  int sigdelset(sigset_t *set,int signo); 从set集合中移除signo信号
  
int sigismember(const sigset_t *set,int signo); signo判断信号是否存在于set集合中

信号处理的过程如下

 

图转自http://blog.csdn.net/rongdeguoqian/article/details/12705603

 

 posted on 2014-03-11 11:02  瞌睡的美人鱼  阅读(303)  评论(0编辑  收藏  举报