Linux 信号通信主要由如下几个步骤组成
- 信号处理函数的注册
- 信号处理函数的注册, 定义在用户空间
- 注册最终通过 rt_sigaction 系统调用发起
- 将用户空间定义的信号处理函数保存到 task_struct 中 sighand 的 action 数组中
- 信号的发送
- 信号的发送通过 kill/tkill/tgkill/rt_sigqueueinfo 函数执行
- 最终通过 __send_signal, 将这个信号添加到对应 进程/线程 的信号待处理链表中
- < 32 为不可靠信号, 待处理列表中存在该信号, 则会自动忽略
- >= 32 为可靠信号, 同一个信号会被添加到信号队列中
- 信号的处理
- 信号的处理会在系统调用或中断处理结束返回用户空间的时机通过 exit_to_usermode_loop 中的 do_signal 执行
- 修改用户函数栈, 插入我们构建的信号处理函数的栈帧 rt_sigframe, 并且将原来的函数栈信息保存在 uc_mcontext 中
- 信号处理函数执行结束之后, 会通过系统调用 rt_sigreturn 恢复之前用户态栈
展开