Linux信号

1. 子进程继承父进程的信号处理方式,信号捕捉函数有意义。但是子进程的未处理信号集设置为空集,子进程的未处理闹钟也被清除。

进程调用exec之后,并没有产生新的进程,只是用新程序替换了当前的正文、堆、栈和数据段,执行新程序的进程还保持闹钟剩余时间,进程信号屏蔽字,未处理信号,资源限制(还包括文件锁、文件创建模式屏蔽字、控制终端、当前工作目录和根目录)

2. fork之后,调用exec函数,将原先父进程设置为要捕捉的信号都更改为他们的默认动作,其它信号状态保持不变。因为原来的信号捕捉函数的地址可能在新程序中无意义。

3. 每个线程都有一个errno,每个线程都有自己的信号屏蔽字,但是共享信号处理函数。进程中的信号是递送到单个线程的,如果信号和硬件故障或者计时器超时相关,则该信号发送到引起该事件的线程去,而其它信号发送到任意一个线程。注意:闹钟定时器是进程资源,所有线程共享相同alarm,进程中的多个线程不可能互不干扰的使用闹钟定时器。

4. 中断系统调用:如果进程在执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用被中断,不再继续执行,返回出错,errno为EINTR。处理理由:一个信号发生了,进程捕捉到,意味着已经发生了某种事情,所以应该是唤醒阻塞的系统调用的好机会。此方法也可以用来限定I/O等操作时间。

此处对应的是UNP网络编程中,read函数出错返回时需要进行的判断,出错并不是代表是函数本身的错误,需要重新启动读操作。

5.编号为0的信号为空信号,kill的参数为0,则kill执行正常错误检查,并不发送信号,用来确定一个进程是否存在,如果不存在,kill返回-1,errno被设置为ESRCH,但注意经过一段时间之后,进程ID可能会被重用,并不能保证正在运行的进程是否是原来的进程。而且,kill非原子操作,可能返回之前,进程恰好终止,所以测试无太大实际意义。

6. pause()函数使得调用进程一直挂起,直到捕捉到一个信号,并执行了一个信号处理程序,从其返回之后,才会返回-1,并将errno设置为EINTR。如果收到信号的默认动作是忽略,则对此函数无影响。如果默认处理方式是终止进程,那更加没有影响,因为进程结束了。

7. 信号发生与其它函数调用之间,存在一个较短的时间,可能产生竞争条件,见APUE 10.10 P253。

信号的交互,即一个信号处理函数正在进行,结果发生了另一个信号,处理函数被迫中断,去执行另一个处理函数,见APUE 10.10,P253。

8. 信号屏蔽字:规定了当前阻塞而不能递送给进程的信号集,直到进程解除对信号的阻塞,或者将该信号处理方式更改为忽略,内核在递送原来被阻塞的信号给进程时,才决定处理方式,即收到之后再处理,不会对信号进行排队,即使多个信号,也只返回一次。可以使用sigpromask检测与更改当前的信号屏蔽,但是此函数是单线程版本,为处理多线程中的信号屏蔽,另一个单独的函数:pthread_sigmask。

9. sigpending函数返回信号集,其中各个信号对于调用进程是阻塞而不能递送的,因而一定是当前未决的。

10. sigsuspend(const sigset_t *sigmask)函数主要是处理信号发生处理与函数调用之间的竞争问题,函数会将信号屏蔽字设置为sigmask指向的值,在捕捉到信号之前或者发生一个会终止该进程的信号之前,进程被挂起,直到捕捉到一个信号且从该信号处理函数返回,则sigsuspend返回,并将信号屏蔽字设置为调用sigsuspend之前的值。

//恢复原来的信号屏蔽字,可能此时有未决信号,会立即进入信号处理函数
sigprocmask(SIG_SETMASK, &oldmask, NULL);
//进程会在此处中断,并且信号处理函数从此处返回
//函数本意是等待一个信号并且从信号处理程序返回,但是并为调用pause之前就发生了信号处理与返回,因此pause会一直阻塞
pause();


sigsuspend可以重新设定当前等待的信号屏蔽字,在等待期间睡眠,但是此函数无法做到等待期间调用其它函数,单线程环境没有太好的解决方案。

多线程可以专门安排一个线程处理信号。

此函数可以配合其它函数实现父子进程的同步。

11. 补充一点:早期的不可靠信号处理signal函数,因为竞争条件,无法做到阻塞信号,以及避免部分竞争条件,因此目前多用sigaction代替,此函数可以一次设置信号屏蔽字,并且在返回时恢复信号屏蔽字,调用信号处理程序时候就能够阻塞特定信号,包括正在被递送的信号,可以保证在处理时,指定信号再次发生时,能够阻塞等待处理。并且除非显示调用sigaction改变之前,设置一直有效。

sigaction设置的屏蔽字对当前的信号处理函数其作用,并不对进程起作用,因此sigprocmask并不能没有。


12. 几个概念:

(1) 函数可重入:函数的执行可能被中断,但是从中断返回之后,函数可以正常按照预期进行,则函数可重入。

(2) 异步信号安全函数:因为信号的异步执行,进程正在执行的指令序列可能被信号处理程序临时中断,首先执行信号处理函数的指令,如果从信号处理程序返回(没有调用exit或longjmp),则继续执行原来的指令序列。因为信号处理的不可预知性,并不能确定何时函数会被中断,如果函数任何时候都可以保证按照原来的预期执行,则称函数是异步可重入的。不可重入的主要原因:(a)调用malloc或free;(b)使用静态数据结构;(c)标准I/O函数。

(2) 线程安全函数:多个控制线程可能同一时间调用同一个函数,如果函数对于多个线程而言是可重入的,则称函数是线程安全的。

(3) 函数线程安全并不能说明对信号处理程序而言,函数是可重入的。


13. sigwait(const sigset *restrict set, int *restrict signop)函数中参数set指明了等待的信号集,signo返回等待的信号。

多个线程等待同一信号,会出现线程阻塞,只有一个线程可以从sigwait返回。

信号被进程捕获,同时线程正在等待该信号,操作系统决定信号的递送方式,但不可能二者同时出现。

此函数用来实现专门的信号处理线程,不让信号处理程序中断主线程。

关于sigwait的使用,仔细阅读此转帖:http://blog.csdn.net/wozaiwogu/article/details/4361456

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值