signal源碼位置:、 信號集合../sched/signal.h 信號結構體:../signal_types.h signal函數:..\kernel\signal.c sigio的概述流程 對於網路IO來說,一旦收到數據,信號機制會發送sigio這個信號 簡單使用sigio,udp可以使用,t ...
- 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的判斷
- 系統調用內部套層調用關鍵函數