信号与线程

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?ca=drs-

原创文章,转载请注明出处。

linux 信号_Linux中的信号处理机制 [四]相关推荐

  1. linux 信号_Linux信号机制

    信号就是一条消息,通知进程系统中发生了什么事,每种信号都对应着某种系统事件.一般的底层硬件异常是由内核的异常处理程序处理的,它对用户进程来说是透明的.而信号机制,提供了一种方法通知用户进程发生了这些异 ...

  2. linux信号传递给进程,bash中的信号处理机制

    Linux 中的信号 信号(Signal)是操作系统中常用的进程通信手段, 主要用来描述特定事件的发生, 进程接收到信号时有以下几种处理方式: 捕获并自定义处理函数: 给signal系统调用传递自定义 ...

  3. linux设备驱动程序中的阻塞机制

    阻塞与非阻塞是设备访问的两种方式.在写阻塞与非阻塞的驱动程序时,经常用到等待队列. 一.阻塞与非阻塞 阻塞调用是指调用结果返回之前,当前线程会被挂起,函数只有在得到结果之后才会返回. 非阻塞指不能立刻 ...

  4. linux 信号_Linux信号量(1)-SYSTEM V

    ​ 信号量概念 信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送 ...

  5. linux 信号_Linux的信号和线程

    Linux的信号和线程-Tech Talk 让技术发出声音​www.ttalk.im 什么是线程 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元. ...

  6. linux命令行界面_Linux中的命令行界面

    linux命令行界面 If you are like most people, you are probably most familiar with using a Graphical User I ...

  7. 浅谈Linux中的信号处理机制(三)

    一晃眼,已经到9月底了,都来不及去感慨时间匆匆.最近常常会想明年的今天我将会在那里干着什么样的工作?对未来又是憧憬又是担忧,压力山大.无论如何现在还是踏踏实实的学习吧,能这样安安静静学习的日子也不多了 ...

  8. linux作业控制 信号,bash中的作业控制机制

    作业控制 在shell中通过command &可以创建后台作业, 通过jobs -l命令可以查看当前shell中维护的作业列表, 包括他们的作业号, 进程号, 运行状态. 其中作业号(jobI ...

  9. linux 查看显卡信号_Linux中查看显卡硬件信息

    Linux中查看显卡硬件信息 https://ywnz.com/linuxjc/67.html lspci -vnn | grep VGA -A 12 lshw -C display 查看当前使用的显 ...

最新文章

  1. Oracle的逻辑结构(表空间、段、区间、块)——Oracle数据块(一)
  2. QT精彩实例分析第5章-0
  3. shiro框架采取MD5+salt方式加密密码
  4. 关于判断后该数据类型是否发生了转变
  5. Tiktok的红利期,你要加入吗?
  6. 使用Bert/ERNIE进行中文短文本分类(附数据集)
  7. Atitit.ide eclipse编译速度慢的解决
  8. linux udp数据包发送间隔,如何每1 ms发送一次UDP数据包?
  9. python爬取网页美文网文章内容
  10. MySQL索引原理以及查询优化
  11. Ubuntu 16.04静态IP设置
  12. 解这道考研题要用克莱默法则的公式吗?
  13. 性能测试,CPU使用率CPU负载率理解
  14. vue3-HTTP请求
  15. 【JAVA】8.继承(图形面积问题)
  16. 如何更清楚的购买自己需要的电脑——配置篇
  17. Taro2.* 小程序配置分享微信朋友圈
  18. Java多态实现人喂养宠物小案例
  19. 学python能赚钱吗-利用python能怎么挣钱
  20. 景深(perspective)

热门文章

  1. Xamarin中国峰会2019
  2. AspNetCore 中使用 InentityServer4(2)
  3. 浅谈开发模式及架构发展
  4. Git 企业开发者教程
  5. 又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)
  6. 分库分表的几种常见形式以及可能遇到的难
  7. C语言试题八十二之输入小写字母,把小写字母转换成大写字母。
  8. linux之用xargs删除这个目录下面后缀为txt的文件(包括子目录)
  9. LeetCode之Palindrome Number(回文数)
  10. C++中之a[5](栈区)和int a=new int[5](堆区)有什么区别