同一个主机的进程间通信:
- 无名管道(PIPE)——适用与任何同主机进程(多亲缘关系进程)——管道是单向的,多进程使用同一管道会产生交叉读写的问题
- 有名管道(FIFO)——依赖文件系统,实现不同进程对文件系统下某个文件的访问
- 消息队列(Message Queue)——同主机任意多进程间通信——存放的数据量有限,适用与少量数据传递
- 共享内存(Share Memory)——同主机任意进程间大量数据通信——数据访问存在竞争问题
- 信号(Signal)——同主机进程间同步机制
- 信号量(semaphore)——同主机进程间异步机制
网络主机间进程通信:
- RPC
- 套接口(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 }
[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