1 linux中的信号
Linux中的信号是用来通知进程发生了异步事件。在原理上,一个进程收到一个信号与一个处理器收到一个中断请可以看成一致的。信号是linux进程间通信机制中的唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也无法提前感知信号什么时候到达由谁发送。当然内核也会因为内部事件给进程发送信号。信号机制除了基本通知功能外,还可以传递附加信息。
常用的信号发送函数有raise kill等 常用的信号注册函数有signal、sigaction等。
2 源码分析
2.1 信号发送
此处拿raise函数分析
raise函数实际调用的是tgkill系统调用,tgkill系统调用实际上是调用的do_tkill函数
3289 static int do_tkill(pid_t tgid, pid_t pid, int sig)
3290 {
3291 struct siginfo info;
3292
3293 clear_siginfo(&info);
3294 info.si_signo = sig;
3295 info.si_errno = 0;
3296 info.si_code = SI_TKILL;
3297 info.si_pid = task_tgid_vnr(current);
3298 info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
3299
3300 return do_send_specific(tgid, pid, sig, &info);
3301 }
上述代码的3293-3298行可以看到初始化了一个info数据结构,其中3294是保存sig信号值,3295是设置错误码,3296行设置是发送的此信号的途径,这里是由tkill发送,3297-3298行是设置pid和uid。3300行可以看到接着调用do_send_specifi。
do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
3261 {
3262 struct task_struct *p;
3263 int error = -ESRCH;
3264
3265 rcu_read_lock();
3266 p = find_task_by_vpid(pid);
3267 if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) {
3268 error = check_kill_permission(sig, info, p);
3269 /*
3270 * The null signal is a permissions and process existence
3271 * probe. No signal is actually delivered.
3272 */
3273 if (!error && sig) {
3274 error = do_send_sig_info(sig, info, p, false);
3275 /*
3276 * If lock_task_sighand() failed we pretend the task
3277 * dies after receiving the signal. The window is tiny,
3278 * and the signal is private anyway.
3279 */
3280