Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1847720
  • 博文数量: 184
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2388
  • 用 户 组: 普通用户
  • 注册时间: 2016-12-21 22:26
个人简介

90后空巢老码农

文章分类

全部博文(184)

文章存档

2021年(26)

2020年(56)

2019年(54)

2018年(47)

2017年(1)

我的朋友

分类: LINUX

2020-09-28 09:43:55

1. 发送信号
内核当中信号相关的成员如下所示

点击(此处)折叠或打开

  1. struct task_struct{
  2. ...
  3.     /* Signal handlers: */
  4.     struct signal_struct        *signal;
  5.     struct sighand_struct __rcu        *sighand;
  6.     sigset_t            blocked;
  7.     sigset_t            real_blocked;
  8.     /* Restored if set_restore_sigmask() was used: */
  9.     sigset_t            saved_sigmask;
  10.     struct sigpending        pending;
  11.     unsigned long            sas_ss_sp;
  12.     size_t                sas_ss_size;
  13.     unsigned int            sas_ss_flags;
  14. ...
  15. };
其中pending表示挂在当前task_struct上的信号,实现时一个链表和一个位图


点击(此处)折叠或打开

  1. struct sigpending {
  2.     struct list_head list;
  3.     sigset_t signal;
  4. };
两个元素都表示外挂信号,不同点就在于排队规则的不同:

点击(此处)折叠或打开

  1. static inline bool legacy_queue(struct sigpending *signals, int sig)
  2. {
  3.     return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
  4. }

也就是说,如果发送的信号小于SIGRTMIN并且已经在外挂信号集合当中,则直接返回,不做处理;如果相反,则挂在链表当中,也就是说以SIGRTMIN为分界线,信号可以分为可丢和排队的两种。

发送完信号就会将对应的task_struct设置TIF_SIGPENDING标志,并且试图唤醒之
2. 处理信号
当一个进程接收到一个信号的时候,并不是立即处理的,而是设置其TIF_SIGPENDING,在其调用schedule的时候进行处理。处理的时候,由于是从系统调用或者中断返回,这里就需要点trick来实现,返回的时候,如果没有信号,则直接返回到进入系统到用的下一条指令即可,但是有信号,需要先执行信号处理函数,然后再返回进入到系统调用的下一条指令。linux当中的做法就是在返回之前,在用户态栈当中插入一个栈帧,栈帧的执行顺序就是保护之前上下文——>设置指令到信号处理函数——>设置处理函数执行完毕之后跳转到恢复函数——>恢复函数调用rt_sigreturn再次进入内核——>内核当中恢复上下文——>返回系统调用
阅读(1220) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~