在了解信号机制前首先来解释一下关于同步和异步的区别,这里举一个通俗易懂的例子就容易理解同步与异步的概念了。
同步:就是你请我吃饭,我听到了就和你吃饭,如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
异步:就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭
信号:又叫软中断,是软件层次上对硬件中断的一种模拟,原理上一个进程收到一个信号与cpu收到一个中断请求是一样的。信号提供了一种处理异步事件的方法。
为什么说信号提供了一种处理异步事件的方法:因为一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底是什么时候到达。
信号处理的三种方式:
(1)忽略此信号
(2)捕捉信号
(3)执行系统默认动作
▲注意:①当程序启动时(即执行exec函数时)exec函数将原先设置为要捕捉的函数设置为默认动作
②当调用fork时,子进程继承父进程的信号处理方式。因为子进程复制了父进程的存储映像,所以信号捕捉函数的地址在子进程中是有意义的。
不可靠信号:早期的unix版本中,信号是不可靠的。不可靠是指信号可能会丢失
①早期版本存在的一个问题是:在进程每次接到信号对其进行处理时,随即将该信号动作复位为默认值
int sig_int( )
.............
signal(SIGINT,sig_int);
.............
sig_int()
{
//因为进程每次接到信号进行处理时,随即将该信号动作复位为默认值。所以这里用signal函数重新注册。但如果在用signal函数重新注册前发生信号,则会按默认进行处理
signal(SIGINT,sig_int);
.......................
}
②早期系统的另一个问题是:在进程不希望某种信号发生时,他不能关闭该信号。进程能做的一确就是忽略该信号。
int sig_int_flag;
main( )
{
int sig_int( );
........
signal(SIGINT,sig_int);
........
while(sig_int_flag==0)//用来忽略其他信号而只等待SIGINT信号
//如果在此处发生信号,pause就会长睡不醒。
pause();
}
sig_int( )
{
signal(SIGINT,sig_int);
sig_int_flag=1;
}
可被中断的系统调用:进程在执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行。该系统调用返回出错,errno被置为EINTR。与被中断的系统调用相关的问题是必须显式的处理出错返回。为了帮助应用程序使其不必处理中断的系统调用,4.2BSD引入了某些被中断的系统调用的自动重启动。
重启动的例子:
again:
if((n=read(fd,buf,BUFFSIZE))<0)
{
if(errno==EINTR)
goto again;
}
可重入函数:一个可重入函数简单来说就是可以被中断的函数。为什么会有不可重如函数存在:因为中断的处理程序与可重入函数都要访问某个临界资源,而又没有对临界资源进行保护所以就容易发生问题。