总算把APUE的信号一章看完了,现在进行一下总结。
信号量:
信号量我们可以理解为软中断,比如进程A正在运行中,突然收到了一个信号,如果进程A捕捉了这个信号,收到信号后,保存当前的运行环境,转而去执行信号处理函数,看以下代码:
int main()
{
signal(SIGINT,fun_sigint);//注册信号处理函数
while(1);
void fun_sigint(int signo)
{
cout<<"收到了SIGINT信号,CTRL+C"<<endl;
}
以上例子中,main函数注册了对于SIGIN信号处理的函数,然后进入while(1)循环,此时在终端ctrl+c,终端就会打印出来”收到了SIGIN信号,CTRL+C”,并且不会退出。 正常情况下我们对于一个前台进程按下ctrl+c,前台进程就会退出,但是这个程序中我们捕捉了ctrl+c发送的信号量(SIGINT),进程收到这个信号量以后,转而去执行信号处理函数。
程序启动和信号量
程序启动的本质是调用了exec函数集中的某个函数,类似以下的代码:
int main()
{
pid_t pid; //在父亲进程
pid=fork();
if(pid==0)//在子进程
{
execlp(arg1,arg2,arg3);//在子进程调用exec函数集去启动一个新的应用,但是用的是子进程的资源(pid等等)
}else if(pid>0)
{
//父进程继续干自己的事情
}
}
调用exec函数后,exec函数将在父进程中设置的信号捕捉动作改成默认值,其他不变,因为exec以后,就是使用的新的程序的代码了,如果在父进程中捕捉某个信号,使用函数f对其进行处理,子进程调用exec以后,不一定有对应的处理函数,所以exec函数将其设置成默认值。
如果在shell中执行:./a.out & ,此时shell自动将后台程序中对ctrl+c(SIGINT)信号的捕捉设置称忽略,这样在shell中终端某个前台进程就不会影响到后台进程。
可再入函数
我们来看这样一种情况:
如果当前进程正在堆上malloc分配空间,这时候来了个信号,当前进程捕捉了这个信号,并且在信号处理函数中有需要进行malloc,这时候将会发生什么?因为malloc申请的内存保持了一链表,如果当前进程的malloc正在修改这个链表,这个时候信号处理函数中的malloc再次来修改同一个链表,这个时候代码将会出现不可预知的错误。
不可再入函数的特征:
1.他们使用静态数据结构
2.他们调用malloc或者free
3.他们是标准的IO函数(实现需要使用全局数据结构)