- 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的判斷
- 系統呼叫內部套層呼叫關鍵函式
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/548274.html
標籤:Linux
