signal
- signal源码位置:、
- 信号集合
../sched/signal.h
- 信号结构体:
../signal_types.h
- signal函数:
..\kernel\signal.c
- 信号集合
sigio的概述流程
- 对于网络IO来说,一旦收到数据,信号机制会发送sigio这个信号
- 简单使用sigio,udp可以使用,tcp不行
网卡接收到数据帧,并发送给协议栈
网络协议栈处理原生包(raw package),再发送给应用程序
应用程序进一步处理
signal的工作流程
-
signal函数和kill函数属于系统调用
-
从三个方面进行梳理
- 对于进程内部,这些信号集合如何保存?
- 调用signal函数时,是怎么保存到进程内部?
- 其他进程调用某个命令(
kill -9 pid
)时,这个信号是如何发送?
-
对于进程内部,这些信号集合如何保存?
- 信号集合用一个结构体数组保存
struct k_sigaction action[_NSIG];
; - 数组大小为64,多处定义
#define _NSIG 64
; struct k_sigaction
- 》维护struct sigaction
-》维护struct sigaction
struct sighand_struct { ... wait_queue_head_t signalfd_wqh; struct k_sigaction action[_NSIG];// 数组维护 }; struct sigaction { ... __sighandler_t _sa_handler; void (*_sa_sigaction)(int, struct siginfo *, void *); };
- 信号集合用一个结构体数组保存
-
调用signal函数时,是怎么保存到进程内部?
- 系统调用内部调用关键函数
do_sigaction()
- 将当前进程中信号数组的第X为进行覆盖
- X为信号的值
#define SIGIO 29
-》总共32个信号
- X为信号的值
int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact{ struct task_struct *p = current, *t;//当前进程的指针 struct k_sigaction *k;// 第一问中提过 ... k = &p->sighand->action[sig-1];//提取出信号集合中该信号对应的位置 ... *k = *act;//该信号的对应位置进行覆盖,如sigio是29,会对索引第28位进行覆盖 ... }
-
额外说明
第一层:`SYSCALL_DEFINE2(signal, int, sig, __sighandler_t, handler)`; 第二层:int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact);
- 系统调用内部调用关键函数
-
其他进程调用某个命令(
kill -9 pid
)时,这个信号是如何发送?- 系统调用内部套层调用关键函数
signalfd_notify()
- 中间套层的函数中会找到kill要发送的pid是否存在,并且找到那个进程
- 发送信号给该进程,并将其唤醒
static inline void signalfd_notify(struct task_struct *tsk, int sig) { if (unlikely(waitqueue_active(&tsk->sighand->signalfd_wqh))) wake_up(&tsk->sighand->signalfd_wqh); } #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL)
-
额外说明
第1层:`SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)`; 第2层:static int kill_something_info(int sig, struct kernel_siginfo *info, pid_t pid); 第3层:static int kill_proc_info(int sig, struct kernel_siginfo *info, pid_t pid); 第4层:int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid); 第5层:int group_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p, enum pid_type type); 第6层:int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p,enum pid_type type); 第7层:int send_signal_locked(int sig, struct kernel_siginfo *info, struct task_struct *t, enum pid_type type); 第8层:static int __send_signal_locked(int sig, struct kernel_siginfo *info,struct task_struct *t, enum pid_type type, bool force); 第9层:static inline void signalfd_notify(struct task_struct *tsk, int sig);
- 第二层:进行pid的判断
- 系统调用内部套层调用关键函数