linux程序管理之訊號處理(1)

2021-09-30 05:24:05 字數 4456 閱讀 3667

訊號是作業系統中一種很重要的通訊方式.近幾個版本中,訊號處理這部份很少有大的變動.我們從使用者空間的訊號應用來分析linux核心的訊號實現方式.

一:訊號有關的資料結構

在task_struct中有關的訊號結構:

struct task_struct

sigset_t的資料結構如下:

//訊號點陣圖.

typedef struct sigset_t;

#define _nsig   64

#ifdef __i386__

# define _nsig_bpw 32

#else

# define _nsig_bpw 64

#endif

#define _nsig_words  (_nsig / _nsig_bpw)

在linux中共有64個訊號.前32個為常規訊號.後32個為實時訊號.實時訊號與常規訊號的唯一區別就是實時訊號會排隊等候.

struct sigpending結構如下:

//訊號等待佇列

struct sigpending ;

struct sighand_struct的結構如下:

struct sighand_struct

同中斷處理一樣,每乙個訊號都對應action中的乙個處理函式.

struct k_sigaction結構如下示:

struct sigaction ;

struct signal_struct結構如下:

struct signal_struct

上述所討論的資料結構可以用下圖表示(摘自<>):

二:更改訊號的處理函式

在使用者空間程式設計的時候,我們常用的註冊訊號處理函式的api有:

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

兩者都可以更改訊號.sigaction是unix後期才出現的介面.這個介面較signal()更為健壯也更為強大:

signal()只能為指定的訊號設定訊號處理函式.而sigaction()不僅可以設定訊號處理函式,還可以設定程序的訊號掩碼.返回設定之前的sigaction結構.sigaction結構在上面已經分析過了.

這兩個使用者空間的介面對應的系統呼叫為別是:

sys_signal(int sig, __sighandler_t handler)

sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact)

我們來分析一下核心是怎麼樣處理的.sys_signal()**如下:

asmlinkage unsigned long

sys_signal(int sig, __sighandler_t handler)

sys_sigaction()的**如下:

asmlinkage int

sys_sigaction(int sig, const struct old_sigaction __user *act,

struct old_sigaction __user *oact)

ret = do_sigaction(sig, act ? &new_ka : null, oact ? &old_ka : null);

//出錯,返回錯誤**.否則返回訊號的sigaction結構

if (!ret && oact)

return ret;

}由此可以看出,兩個函式最終都會呼叫do_sigaction()進行處理.該函式**如下:

rm_from_queue_full()用來將等待佇列中的訊號刪除.並清除等待佇列中的點陣圖.**如下:

static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)

}return 1;

}上面有關posix標準,請自行查閱相關資料.

三:傳送訊號

在使用者空間中,我們可以用kill()給指定程序傳送相應訊號.它在使用者空間的定義如下所示:

int kill(pid_t pid, int signo)

pid的含義如下所示:

pid > 0 將訊號傳送給程序id為pid的程序。

pid == 0 將訊號傳送給其程序組id等於傳送程序的程序組id,而且傳送程序有許可權向其傳送訊號的所有程序。

這裡用的術語「所有程序」不包括實現定義的系統程序集。對於大多數u n i x系統,系統程序集包括:交換程序(pid 0),init (pid 1)以及頁精靈程序(pid 2)。

kill()的系統呼叫介面為sys_kill():

asmlinkage long

sys_kill(int pid, int sig)

轉到kill_something_info():

static int kill_something_info(int sig, struct siginfo *info, int pid)

else if (pid == -1)

}read_unlock(&tasklist_lock);

ret = count ? retval : -esrch;

} else if (pid < 0) else

rcu_read_unlock();

return ret;

}假設pid > 0.轉入kill_pid_info().即把訊號傳送到pid的程序

int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)

在這裡將pid轉化為對應的task_struct.然後呼叫group_send_sig_info().**如下:

int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)

}return ret;

}首先,要給程序傳送訊號,應該先判斷它是否具有這樣的許可權.判斷的依據為:

如果是使用者空間傳送的訊號,檢查其是否有相應的許可權

必須要滿足以下幾個條件中的任乙個才可以傳送:

1:傳送訊號者必須擁有相關的權能

2: 如果是傳送sigcont且傳送程序與種目標程序處於同乙個註冊會話中

3:屬於同乙個使用者的程序

轉入__group_send_sig_info():

int

__group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)

具體的程序傳送過程是在send_signal()完成的.它的**如下:

static int send_signal(int sig, struct siginfo *info, struct task_struct *t,

struct sigpending *signals)

} else if (!is_si_special(info))

out_set:

//更新等待佇列的signal 位圖,表示收到了乙個訊號,但沒有處理

sigaddset(&signals->signal, sig);

return ret;

}經過這個過程,我們看到了程序怎麼將訊號傳送到另外的程序.特別要注意的是,目標程序接收到訊號之後會將其喚醒.這時如果目標程序是系統呼叫阻塞狀態就會將它的系統呼叫中斷.

另外,核心經常使用force_sig_info()/force_sig()來給程序傳送訊號.這樣的訊號經常不可以忽略,不可以阻塞.我們來看一下它的處理.**如下:

int

force_sig_info(int sig, struct siginfo *info, struct task_struct *t)

}//"特殊"的訊號傳送

ret = specific_send_sig_info(sig, info, t);

spin_unlock_irqrestore(&t->sighand->siglock, flags);

return ret;

}

Linux程序訊號 訊號處理

一 訊號相關概念 1.實際執行訊號的處理動作稱為訊號遞達 delivery 2.訊號從產生到遞達之間的狀態稱為訊號未決 pending 不一定會立即delivery 3.程序可以選擇阻塞 block 某個訊號。不會遞達 4.被阻塞的訊號產生時將保持在未決狀態,知道程序解除對此訊號 的阻塞,才會執行遞...

76 訊號之程序對訊號的處理

預設處理 忽略處理 捕獲處理 預設和忽略都不用深究了,之前就都是預設忽略的 捕獲處理 註冊等錢程序在os中,某乙個訊號的處理方法,註冊乙個處理方法,指向的函式就是處理方法 用signal函式吃力sigint訊號 細節 signal的返回值是之前的處理方法 預設 忽略 捕獲 signal繫結乙個捕獲函...

linux 程序訊號處理程式繼承

1.執行exec後的訊號狀態 執行exec後,新程式替換了當前程序的正文段 資料段 堆 棧 當執行乙個程式時,所有訊號的狀態都是系統預設或忽略。當呼叫exec函式後會將原先設定為要捕捉的訊號都更改為預設動作,其他訊號的狀態則不變 乙個程序原先要捕捉的訊號,當其exec乙個新的程式後,就不能在捕捉了,...