网站建设术语 英文,网站制作结构,好用app制作,wordpress最佳速度优化信号与线程Unix的信号机制在诞生之初#xff0c;生活在只有进程(process)的相对单纯的环境中。自从Unix世界有了线程(thread)的概念#xff0c;信号就被赋予了发往进程中某个特定线程的能力#xff0c;当然#xff0c;这也增加了整个信号机制实现的复杂度。本系列的前面三篇…信号与线程Unix的信号机制在诞生之初生活在只有进程(process)的相对单纯的环境中。自从Unix世界有了线程(thread)的概念信号就被赋予了发往进程中某个特定线程的能力当然这也增加了整个信号机制实现的复杂度。本系列的前面三篇文章都是基于进程进行的信号实现机制的讨论本文将着重介绍Linux中信号和线程之间的交互。发送信号给线程无论是kill()还是sigqueue()都只能向进程发送信号在Linux中要向进程内的线程发送信号需要使用tkill()或者tgkill()int 两个函数中tid都是代表目标线程的PID但tgkill()比tkill()多了一个tgid的参数。tgid是目标线程所在进程的PID它可以用来防止向错误的线程发送信号。发送方给目标线程发送信号时可能目标线程已经因为某种原因退出了按照Linux中PID的分配规则退出线程/进程的PID可被分配给其他的线程/进程使用。这种情况下如果使用tkill()就可能出现将信号发送到不相干的线程上。引入tgid可以帮助进行目标线程所在进程的校验这样出现错发的可能性就被大大地降低了。线程对信号的接收根据POSIX标准的定义进程内的所有线程共享进程的信号处理函数当进程内的一个线程为某个信号注册了处理函数另一个线程可以更改这个处理函数。在Linux的实现中线程作为独立的调度实体也有自己的task_struct同一进程的不同线程的task_struct的sighand将指向同一个包含信号处理函数列表的sighand_struct。但是每个线程可以有单独的pending位图/队列和block位图。如果一个信号是发送给线程的那么内核在递送该信号时会将它放入线程私有的pending位图/队列中之后根据目标线程的block位图的设置直接由目标线程处理就可以了。如果信号是发送给一个进程的那么该信号在递送时将被内核放入进程的pending位图/队列中由进程内的所有线程共享。接下来内核会从进程的各个线程中挑选一个block位图中没有屏蔽该信号的线程来执行对应的信号处理函数其中进程的主线程将被内核优先选择。但是有一些信号是需要进程内的全体线程都做出响应的比如前面提到的令进程闻风丧胆的SIGKILL它一旦到来就不会留下一个活口。当一个线程即将被内核调度执行而该线程私有的penging位图/队列和所在进程共享的penging位图/队列上都有待处理的信号时内核将优先向线程递送私有的penging位图/队列上的信号int 作为Unix时代的产物前面讲到的sigprocmask()函数最初是用来设置进程的block位图的但是同pending位图/队列不同的是并没有一个所谓的线程共享的block位图的概念所以在多线程环境下sigprocmask()的语义也就变成了设置线程的block位图。当然为了语义更加明显你可以使用POSIX线程库提供的pthread_procmask()函数两者的参数和行为都是一样的。参考《Linux环境编程从应用到内核》第6章Understanding the Linux Kernel 第3版第11章UNIX Internals: The New Frontiers 第4章http://kernel.meizu.com/linux-signal.html https://www.ibm.com/developerworks/cn/linux/l-ipc/part2/index1.html?cadrs- 原创文章转载请注明出处。