linux信号量
1. 什么是不可靠信号
信号可能丢失
2. 什么是信号屏蔽
信号有信号产生和信号传递两个步骤,如果设置了信号屏蔽,那么被设置的信号可以产生,但不会被传递。但撤销该信号屏蔽后,就会把先前的已经产生的传递到相应地方,不过如果先前该信号产生了多次,最终也只会传递一次。有了信号屏蔽,这样就可以保证在进行信号处理时,不会丢失该信号的再次产生。
3. 信号处理的相关api
Void *Singal(int signo, void (*func)(int);//线程不安全
Int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);//线程不安全
Int sigaction(int signo, const struct sigaction *restrict act, strcut sigaction *restrict oact);
4. 别用Signal,用sigaction
可以通过signal或者sigaction函数来设置信号处理函数,但signal函数太过古老,因此推荐使用sigaction。理由如下:
Ø sigaction可以提供更多接收到信号的信息。
Ø 调用完信号处理函数后重新设置处理函数不会对sigaction有影响,因为sigaction默认是不会去重置处理函数的,同时在执行处理函数会屏蔽掉该信号,也不会有竞争。
Ø signal函数在某些系统中会默认重启被中断的系统调用,而sigaction默认不会这样做。
Ø signal函数在多线程环境中的行为是未定义的,必须使用sigaction函数。
5. 信号,多进程,多线程
Ø Fork出的子进程继承父进程的信号处理方式,因为子进程开始时复制了父进程的存储映像,所以信号捕捉函数的地址在子进程中是有意义的。
Ø Exec函数将原先设置为要捕捉的信号都更改为它们的默认动作。
Ø 每个线程都有自己的信号屏蔽字,但是信号的处理是所有线程共享的。
6. SIGHUP信号与控制终端
UNIX中进程组织结构为 session (会话)包含一个前台进程组及一个或多个后台进程组,一个进程组包含多个进程。一个session可能会有一个session首进程,而一个session首进程可能会有一个控制终端。一个进程组可能会有一个进程组首进程。进程组首进程的进程ID与该进程组ID相等。这儿是可能会有,在一定情况之下是没有的。与终端交互的进程是前台进程,否则便是后台进程。
SIGHUP会在以下3种情况下被发送给相应的进程:
1、终端关闭时,该信号被发送到session首进程以及作为job提交的进程(即用 & 符号提交的进程)
2、session首进程退出时,该信号被发送到该session中的前台进程组中的每一个进程
3、若父进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进程组中的每一个进程。
系统对SIGHUP信号的默认处理是终止收到该信号的进程。所以若程序中没有捕捉该信号,当收到该信号时,进程就会退出。
解决办法a、自己在程序里屏蔽sighup信号;b、使用nohup
7. 内核实现
参考《深入理解linux内核》