Linux 信号模型是基于进程模型而设计的,信号的问世远早于线程;自然而然,线程与信号之间就会存在一些冲突,其主要原因在于:信号既要能够在传统的单线程进程中保持它原有的功能、特性,与此同时, 又需要设计出能够适用于多线程环境的新特性!
信号与多线程模型之间结合使用,将会变得比较复杂,需要考虑的问题将会更多,在实际应用开发当中,如果能够避免我们应尽量避免此类事情的发生;但尽管如此,事实上,信号与多线程模型确实存在于实际的应用开发项目中。下面我们就来讨论信号与线程之间牵扯的问题。
信号如何映射到线程?
信号模型在一些方面是属于进程层面(由进程中的所有线程线程共享)的,而在另一些方面是属于单个线程层面的,以下对其进行汇总:
- 信号的系统默认行为是属于进程层面。前文介绍到,每一个信号都有其对应的系统默认动作, 当进程中的任一线程收到任何一个未经处理(忽略或捕获)的信号时,会执行该信号的默认操作, 信号的默认操作通常是停止或终止进程。
- 信号处理函数属于进程层面。进程中的所有线程共享程序中所注册的信号处理函数;
- 信号的发送既可针对整个进程,也可针对某个特定的线程。在满足以下三个条件中的任意一个时, 信号的发送针对的是某个线程:
- 产生了硬件异常相关信号,譬如 SIGBUS、SIGFPE、SIGILL 和 SIGSEGV 信号;这些硬件异常信号在某个线程执行指令的过程中产生,也就是说这些硬件异常信号是由某个线程所引起; 那么在这种情况下,系统会将信号发送给该线程。
- 当线程试图对已断开的管道进行写操作时所产生的 SIGPIPE 信号;
- 由函数 pthread_kill()或 pthread_sigqueue()所发出的信号,稍后介绍这两个函数;这些函数允许线程向同一进程下的其它线程发送一个指定的信号。
除了以上提到的三种情况之外,其它机制产生的信号均属于