信号机制是linux内核为进程通信提供的的一套局部中断机制,就是进程在执行过程中如果收到了信号就打断现在的执行,转而去执行进程的信号处理程序,处理完成后再从中断处继续执行。需要保证在在没有信号的情况下,信号处理函数不会影响主进程的执行。考虑下面的实例程序:
接收函数:
#include<stdio.h>
#include<signal.h>
void sig_usr(int signo)
{
printf("I am sig_usr!");
signal(SIGUSR1,sig_usr);
}
int main()
{
signal(SIGUSR1,sig_usr);//设置信号处理函数
printf("my pid is %d\n",getpid());//答应pid,方便发送函数发送信号
for(;;)
pause();//进程暂停
return 0;
}
发送函数:
#include<stdio.h>
#include<signal.h>
int main(int argc,char **argv)
{
int pid = atoi(argv[1]);
int ret = kill(pid,SIGUSR1);//项进程号为pid的进程发送信号
if(ret!=0)
printf("send singal error. \n");
return 0;
}
<1>在发送函数中,signa()是一个库函数,调用后产生软中断,最终映射到内核的sys_signal()中,在该函数中声明一个信号处理的结构体sigaction,并使用当前进程的信息初始化该结构体。其中包括信号处理函数的入口地址,现场恢复函数的入口地址等。然后该进程task_stucture中的sigaction的特定块与该结构体绑定,也就实现了进程与进程处理函数的绑定。
<2>当进程运行到pause()的时候,会将进程设置为可中断的等待状态,并调用schedule()函数进程进程的切换。
<3>sending函数运行,运行到kill()函数的时候,会产生中断,并映射到sys_kill()中。这个函数会寻找到进程号为pid的进程,并将其task_structure的signal中相应的位置1.
<4>sending函数的时间片用完,转而再次调用schedule()函数,当调用schedule的时候会便利每一个进程的signal,假如发现相应的位为1,并且该进程处于可中断状态,就将该进程设置为就绪状态。
<5>当再次调用到recieve函数的时候,会先去调用信号处理函数,然后回到主程序中。
至此,基于信号的进程间通信完成。