往process group 发送signal - linux kernel 实现浅欣赏
2017-03-23 21:47
267 查看
以前的浅析:
http://blog.csdn.net/leesagacious/article/details/53678666
一图胜千言,先看一幅图
http://blog.csdn.net/leesagacious/article/details/53678666
一图胜千言,先看一幅图
/** kill(pid_t pid,int sig) kill 不是杀死进程,他是发信号 可以向特定的进程组发送信号, 好下面我们就看看linux是怎么实现的 if (kill(-10,SIGUSR1) < 0){ if (errno == ESRCH){ //目标进程或者进程组不存在 perror("exit"); exit(EXIT_FAILURE); } if (errno == EPERM){ //该进程没有权限向目标进程发送信号 }; } */ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) { /* 信号携带的一些信息,下面会为他赋值 int si_signo; int si_errno; int si_code; 怎么不kzalloc()了 ? 用栈上的内存了? 哈哈! */ struct siginfo info; /* 赋值初始化把 si_signo:信号的值 si_errno:产生信号的错误码, si_code: 信号的来源; SI_USER :调用kill的用户进程, SI_ASYNCIO : 异步I/O操作完成后 SI_TIMER : POSIX定时器到期 SI_KERNEL :内核产生的信号 */ info.si_signo = sig; info.si_errno = 0; info.si_code = SI_USER; info.si_pid = task_tgid_vnr(current); // sender pid info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); //sender uid /* 看pid 还是没有变化,还是我们从用户空间传递过来的 */ return kill_something_info(sig, &info, pid); }
static int kill_something_info(int sig, struct siginfo *info, pid_t pid) { int ret; /* 看,用户空间传递过来的pid,就是在这里才发生化学反应 就是pid > 0、 -1 之类的比较,决定将该信号按照你的意愿发送到哪里 上图简单的画出了: > 0 : 向 pid 进程发 =-1 : 发所有,init、自身是除外的,为什么?下面分析, 所以,进程自己想用kill 自杀,在Linux Kernel中是不允许的,哈哈! < -1 : 看下面的具体实现 */ /* pid > 0 : 发送给进程 pid 这里最先处理的是这一种情况,因为我们使用kill发送信号,大多数都是发送给一个特定的进程的,我们暂不分析这个,我们关注pid < -1 的情况 */ if (pid > 0) { ..... return ret; } /* 暂不分析 */ if (pid != -1) { ..... } else { /* 这个好狠呀,遍历系统中所有的进程 task_struct 整个队列,它说要整个遍历一次, 代价是很大的, <<Linux 内核设计与实现 第三版>>中描述:没有充足的理由别这样做 ! 作者在这里违反了这一条,不知道作者写到这儿的时候,有没有想起 这句话 */ for_each_process(p) { /* 好,如果查找到了一个进程之后,看它是怎么做的 task_pid_vnr(p) : 取得这个 进程的pid 然后那么就 比较呗 ! 看,是不能给自己进程发送信号的把 same_thread_group () { return p1->signal == p2->signal; } */ if (task_pid_vnr(p) > 1 && !same_thread_group(p, current)) { /* 看传递的参数,都是很熟悉的了吧 sig : 用户传递过来的sig info: 一开始 栈上那块内存,携带一些信号的信息 p : 通过上面两个函数校验后系统中的每一个进程 好,看它是怎么实现的 */ int err = group_send_sig_info(sig, info, p); } } } }
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) { int ret; rcu_read_lock(); /* 发送信号的权限不正确 暂且不分析 */ ret = check_kill_permission(sig, info, p); rcu_read_unlock(); /* 发信号吧,但是这个函数不是最终发信号的,它包装了一些底层的函数, 具体是挂入那个队列的事情了,看第 4 个参数,group 是 1, 详细情况,你可以看我的另一篇博文了,哈哈! http://blog.csdn.net/leesagacious/article/details/53678666 */ if (!ret && sig) ret = do_send_sig_info(sig, info, p, true); return ret; }
相关文章推荐
- genl-netlink 协议 Linux kernel 实现 欣赏
- Linux Kernel 调度实现 -----欣赏
- 实现两个程序mysignal、mycontrl,mycontrl给mysignal发送SIGINT信号,控制mysignal是否在屏幕打印“hello”字符串。
- signal 的"冰山理论" -- Linux Kernel 实现赏析
- Device Tree --- Linux Kernel 实现欣赏
- uevent内核事件与netlink机制的交互 -Linux Kernel实现欣赏
- Usb + Serial + Net --- Linux Kernel 实现欣赏
- Interrupt 架构之美 -- Linux Kernel 实现欣赏
- Process scheduling - Linux Kernel 实现 欣赏
- Driver 分层的思想 -- Linux Kernel 内核实现欣赏
- 关于VC++中,两种自定义消息的发送与接收的方法实现进行说明。
- [原创]将TDC进行到底(2):实现数据的刷新(只刷新表格数据)|并欣赏将TDC和StedyMenu结合的效果
- asp.net能实现身份认证的EMAIL发送方法(c#版本)
- 用VC实现发送和接受短信
- 挂接CreateProcessW实现对进程创建的完全控制
- 在程序中实现网站链接和发送邮件(zz)
- 利用SAP Offcie组件实现邮件发送功能
- 能实现身份认证的EMAIL发送方法
- 轻松实现用SMTP发送需用户验证的邮件!
- 使用.ashx文件处理IHttpHandler实现发送文本及二进制数据的方法。