glibc-raise源码阅读
摘要: 本文通过分析glibc中raise函数的源码,揭示其实现原理,指出其调用tgkill函数以确保多线程环境下信号正确传递,且在信号处理结束后返回。作者还结合man手册说明raise在单线程和多线程中的作用,以及其在用户内核态切换中的作用时机,强调raise的信号发送机制与进程控制紧密相关。 (评价: A)
问题
关于raise
函数,有几个想调查的问题:
raise
是怎么实现的?raise
的作用时机?
源码
先来看raise的实现, 代码比较简单, 我们也无需递归地去看每一个函数地实现.
raise调用的就是tgkill. tgkill相比kill和tkill, 增加了多线程的保护, 通过tid和tgid基本保证信号传递到正确的线程, 而不会因为线程的消亡和构建而传递到错误的线程.
|
|
raise
看起来很简单, 我们也可以通过man raise
来详细了解一下, 其说明的是:
- raise在单线程中等同于kill;
- raise在多线程中等同于pthread_kill;
- raise在信号处理函数处理结束后返回;
- raise是多线程安全的;
- glibc 2.3.3版本后raise调用的是tgkill.(本文即是tgkill)
所以我们可以解答开头的问题:
raise
是怎么实现的?
等同于tgkill, rasie发送信号给线程(进程), 然后调用对应的信号处理函数. 回忆上一篇《glibc-abort源码阅读》, 调用abort的时候就是调用raise发送SIGABRT信号, 会有SIG_DFL之类的处理函数绑定SIGABRT信号, 从而造成进程退出.
raise
的作用时机?
同信号处理, 参考《进程控制和通信(四) · PCB介绍》可以知道, raise是在用户陷入内核态再从内核态返回用户态的过程中会被处理. 所以, abort的作用时机也是等同于raise.