日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

linux內(nèi)核中的信號(hào)機(jī)制

 lchjczw 2013-04-14

linux內(nèi)核中的信號(hào)機(jī)制--信號(hào)機(jī)制的管理結(jié)構(gòu)

Kernel version:2.6.14

CPU architecture:ARM920T

Author:ce123(http://blog.csdn.net/ce123)


信號(hào)只是一個(gè)數(shù)字,數(shù)字為0-31表示不同的信號(hào),如下表所示。

編號(hào)

信號(hào)名

默認(rèn)動(dòng)作

說(shuō)明

1

SIGHUP

進(jìn)程終止

終端斷開(kāi)連接

2

SIGINT

進(jìn)程終止

用戶在鍵盤(pán)上按下CTRL+C

3

SIGQUIT

進(jìn)程意外結(jié)束(Dump)

用戶在鍵盤(pán)上按下CTRL+\

4

SIGILL

進(jìn)程意外結(jié)束(Dump)

遇到非法指令

5

SIGTRAP

進(jìn)程意外結(jié)束(Dump)

遇到斷電,用于調(diào)試

6

SIGABRT/SIGIOT

進(jìn)程意外結(jié)束(Dump)

 

7

SIGBUS

進(jìn)程意外結(jié)束(Dump)

總線錯(cuò)誤

8

SIGFPE

進(jìn)程意外結(jié)束(Dump)

浮點(diǎn)異常

9

SIGKILL

進(jìn)程終止

其他進(jìn)程發(fā)送SIGKILL將導(dǎo)致目標(biāo)進(jìn)程終止

10

SIGUSR1

進(jìn)程終止

應(yīng)用程序可自定義使用

11

SIGSEGV

進(jìn)程意外結(jié)束(Dump)

非法的內(nèi)存訪問(wèn)

12

SIGUSR2

進(jìn)程終止

應(yīng)用程序可自定義使用

13

SIGPIPE

進(jìn)程終止

管道讀取端已經(jīng)關(guān)閉,寫(xiě)入端進(jìn)程會(huì)收到該信號(hào)

14

SIGALRM

進(jìn)程終止

定時(shí)器到時(shí)

15

SIGTERM

進(jìn)程終止

發(fā)送該信號(hào)使目標(biāo)進(jìn)程終止

16

SIGSTKFLT

進(jìn)程終止

堆線錯(cuò)誤

17

SIGCHLD

忽略

子進(jìn)程退出時(shí)會(huì)向父進(jìn)程發(fā)送該信號(hào)

18

SIGCONT

忽略

進(jìn)程繼續(xù)執(zhí)行

19

SIGSTOP

進(jìn)程暫停

發(fā)送該信號(hào)會(huì)使目標(biāo)進(jìn)程進(jìn)入TASK_STOPPED狀態(tài)

20

SIGTSTP

進(jìn)程暫停

在終端上按下CTRL+Z

21

SIGTTIN

進(jìn)程暫停

后臺(tái)進(jìn)程從控制終端讀取數(shù)據(jù)

22

SIGTTOU

進(jìn)程暫停

后臺(tái)進(jìn)程從控制終端讀取數(shù)據(jù)

23

SIGURG

忽略

socket收到設(shè)置緊急指針標(biāo)志的網(wǎng)絡(luò)數(shù)據(jù)包

24

SIGXCPU

進(jìn)程意外結(jié)束(Dump)

進(jìn)程使用CPU已經(jīng)超過(guò)限制

25

SIGXFSZ

進(jìn)程意外結(jié)束(Dump)

進(jìn)程使用CPU已經(jīng)超過(guò)限制

26

SIGVTALRM

進(jìn)程終止

進(jìn)程虛擬定時(shí)器到期

27

SIGPROF

進(jìn)程終止

進(jìn)程Profile定時(shí)器到期

28

SIGMNCH

忽略

進(jìn)程終端窗口大小改變

29

SIGIO

進(jìn)程暫停

用于異步IO

29

SIGPOLL

進(jìn)程暫停

用于異步IO

30

SIGPWR

進(jìn)程暫停

電源失效

31

SIGUNUSED

進(jìn)程暫停

保留未使用

注意在上標(biāo)中的默認(rèn)動(dòng)作是指,在沒(méi)有任何程序?yàn)橄鄳?yīng)的信號(hào)設(shè)置信號(hào)處理函數(shù)的情況下,內(nèi)核接收到該信號(hào)的默認(rèn)處理方式,但在實(shí)際中,有可能不是這樣的。另外,在這里,進(jìn)程終止一般是指進(jìn)程通過(guò)do_exit()退出,進(jìn)程意外結(jié)束(Dump)則表示進(jìn)程遇到了一個(gè)異常。默認(rèn)情況下,內(nèi)核會(huì)根據(jù)進(jìn)程當(dāng)時(shí)的內(nèi)存情況,在進(jìn)程的當(dāng)前目錄中生成一個(gè)Core Dump文件,以后用戶可以通過(guò)這個(gè)文件分析進(jìn)程異常的原因。這個(gè)工作主要通過(guò)do_coredump()來(lái)完成。

由于早期只有31個(gè)信號(hào),內(nèi)核僅僅使用一個(gè)32位的變量signal來(lái)表示進(jìn)程接收到的信號(hào),因此如果要向一個(gè)進(jìn)程發(fā)送一個(gè)信號(hào),就把signal的第n位設(shè)置為1,這非常類似中斷請(qǐng)求寄存器SRCPND寄存器,同時(shí),還有一個(gè)blocked的變量,用來(lái)屏蔽信號(hào),這類似中斷屏蔽寄存器INTMSK。這樣做的好處是可以“很快”判斷出一個(gè)進(jìn)程收到了哪些信號(hào),如果采用鏈表或者數(shù)組,則需要掃描整個(gè)隊(duì)列,但這也帶來(lái)了新的問(wèn)題,如果向一個(gè)進(jìn)程發(fā)送了SIGINT信號(hào),在這個(gè)信號(hào)處理之前,再次發(fā)送SIGINT,當(dāng)這個(gè)進(jìn)程開(kāi)始處理信號(hào)時(shí),它只知道收到了SIGINT信號(hào),而無(wú)法判斷出有幾個(gè)SIGINT需要處理。此后加入了信號(hào)隊(duì)列,把收到的信號(hào)保存在這個(gè)隊(duì)列中,就可以很好的解決這個(gè)問(wèn)題了。但是為了兼容的目的,仍能保留了舊的信號(hào)處理方式,因此1-32還是按原有的方式進(jìn)行處理,而33-64則使用新的機(jī)制,為了區(qū)別對(duì)待,編號(hào)為33-64的信號(hào)又稱為實(shí)時(shí)信號(hào)。需要注意的是:這里的“實(shí)時(shí)”和實(shí)時(shí)操作系統(tǒng)中的“實(shí)時(shí)”沒(méi)有任何聯(lián)系,實(shí)時(shí)信號(hào)在處理速度上并不會(huì)比普通信號(hào)快,它們之間的區(qū)別就是:普通信號(hào)會(huì)對(duì)多次的同一個(gè)信號(hào)進(jìn)行“合并”處理,而實(shí)時(shí)信號(hào)會(huì)一一處理。因此我們這里僅討論普通信號(hào)。

信號(hào)機(jī)制的相關(guān)管理結(jié)構(gòu)位于task_struct結(jié)構(gòu)中,其主要結(jié)構(gòu)如下圖所示。


實(shí)時(shí)信號(hào)引入了信號(hào)隊(duì)列,為了處理上的方便,普通信號(hào)也使用了信號(hào)隊(duì)列,僅僅從數(shù)字上無(wú)法區(qū)分實(shí)時(shí)信號(hào)和普通信號(hào)。由于在linux中,進(jìn)程對(duì)象和線程對(duì)象都是task_struct,因此需要區(qū)別對(duì)待線程的信號(hào)和進(jìn)程的信號(hào)。在上圖中,Private Signal Queue是線程(在linux中稱為輕權(quán)進(jìn)程)信號(hào)隊(duì)列,而Shared Signal Queue是進(jìn)程(在linux中被稱為進(jìn)程組)信號(hào)隊(duì)列。對(duì)于進(jìn)程信號(hào),則由進(jìn)程組中的每一個(gè)線程共享。例如,在上圖中,pending和shared_pending分別是Private Signal Queue和Shared Signal Queue其類型都是sigpending(/include/linux/signal.h),定義如下:

  1. struct sigpending {  
  2.     struct list_head list;  
  3.     sigset_t signal;  
  4. };  

list用于連接信號(hào)隊(duì)列,signal是一個(gè)位圖,每一位表示一個(gè)對(duì)應(yīng)的信號(hào),用于指示信號(hào)隊(duì)列中有哪些信號(hào)等待處理,其類型為sigset_t(include/asm-arm/signal.h),其定義如下:

  1. #define _NSIG       64  
  2. #define _NSIG_BPW   32  
  3. #define _NSIG_WORDS (_NSIG / _NSIG_BPW)  
  4.   
  5.   
  6. typedef struct {  
  7.     unsigned long sig[_NSIG_WORDS];  
  8. } sigset_t;  

sigset_t是一個(gè)數(shù)組,總共有64位,對(duì)應(yīng)64個(gè)信號(hào)位圖(32個(gè)普通信號(hào)和32個(gè)實(shí)時(shí)信號(hào))。在以后的信號(hào)發(fā)送的分析中,我們會(huì)看到,對(duì)于普通信號(hào),只需要把sigset_t中對(duì)應(yīng)的位置1就可以了,而對(duì)于實(shí)時(shí)信號(hào),還需要把相關(guān)信息添加到list的信號(hào)隊(duì)列,信號(hào)隊(duì)列類型為sigqueue(include/linux/signal.h),定義如下:

  1. /*  
  2.  * Real Time signals may be queued.  
  3.  */  
  4.   
  5. struct sigqueue {  
  6.     struct list_head list;  
  7.     spinlock_t *lock;  
  8.     int flags;  
  9.     siginfo_t info;  
  10.     struct user_struct *user;  
  11. };  
sigqueue中的list是隊(duì)列鏈表指針,info為這個(gè)信號(hào)的相關(guān)信息,其定義如下(include/asm-generic/siginfo.h):

  1. typedef struct siginfo {  
  2.     int si_signo;  
  3.     int si_errno;  
  4.     int si_code;  
  5.   
  6.     union {  
  7.         int _pad[SI_PAD_SIZE];  
  8.   
  9.         /* kill() */  
  10.         struct {  
  11.             pid_t _pid;     /* sender's pid */  
  12.             __ARCH_SI_UID_T _uid;   /* sender's uid */  
  13.         } _kill;  
  14.   
  15.         /* POSIX.1b timers */  
  16.         struct {  
  17.             timer_t _tid;       /* timer id */  
  18.             int _overrun;       /* overrun count */  
  19.             char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];  
  20.             sigval_t _sigval;   /* same as below */  
  21.             int _sys_private;       /* not to be passed to user */  
  22.         } _timer;  
  23.   
  24.         /* POSIX.1b signals */  
  25.         struct {  
  26.             pid_t _pid;     /* sender's pid */  
  27.             __ARCH_SI_UID_T _uid;   /* sender's uid */  
  28.             sigval_t _sigval;  
  29.         } _rt;  
  30.   
  31.         /* SIGCHLD */  
  32.         struct {  
  33.             pid_t _pid;     /* which child */  
  34.             __ARCH_SI_UID_T _uid;   /* sender's uid */  
  35.             int _status;        /* exit code */  
  36.             clock_t _utime;  
  37.             clock_t _stime;  
  38.         } _sigchld;  
  39.   
  40.         /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */  
  41.         struct {  
  42.             void __user *_addr; /* faulting insn/memory ref. */  
  43. #ifdef __ARCH_SI_TRAPNO  
  44.             int _trapno;    /* TRAP # which caused the signal */  
  45. #endif  
  46.         } _sigfault;  
  47.   
  48.         /* SIGPOLL */  
  49.         struct {  
  50.             __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */  
  51.             int _fd;  
  52.         } _sigpoll;  
  53.     } _sifields;  
  54. } siginfo_t;  
上圖中的sighand保存信號(hào)的處理函數(shù)指針,其作用類似于中斷向量表,類型為sighand_struct(include/linux/sched.h),定義為:

  1. struct sighand_struct {  
  2.     atomic_t        count;  
  3.     struct k_sigaction  action[_NSIG];  
  4.     spinlock_t      siglock;  
  5. };  
_NSIG定義在asm-arm/signal.h中,為64,數(shù)組action,對(duì)應(yīng)64個(gè)信號(hào)處理函數(shù)的相關(guān)信息,烈性為k_sigaction,在arm平臺(tái)上,k_sigaction(include/asm-arm/signal.h)是死噶長(zhǎng)提哦你的一個(gè)包裝,定義如下:

  1. struct k_sigaction {  
  2.     struct sigaction sa;  
  3. };  
sigantion(include/asm-arm/signal.h)的定義如下:

  1. struct sigaction {  
  2.     __sighandler_t sa_handler;  
  3.     unsigned long sa_flags;  
  4.     __sigrestore_t sa_restorer;  
  5.     sigset_t sa_mask;       /* mask last for extensibility */  
  6. };  

sa_handler就是信號(hào)處理函數(shù)指針。另外在task_struct結(jié)構(gòu)中還有一個(gè)blocked可以用來(lái)屏蔽信號(hào)。明白了上面的主要數(shù)據(jù)結(jié)構(gòu)的作用之后,很容易想到信號(hào)的處理主要有以下幾方面。

  • 設(shè)置信號(hào)回調(diào)函數(shù):內(nèi)核吧函數(shù)的相關(guān)信息保存到對(duì)應(yīng)的sigantion結(jié)構(gòu)中。
  • 信號(hào)的發(fā)送:通過(guò)相關(guān)系統(tǒng)調(diào)用吧一個(gè)指定的信號(hào)發(fā)送到目標(biāo)進(jìn)程,如果該信號(hào)沒(méi)有被屏蔽,就把信號(hào)的相關(guān)信息添加到信號(hào)隊(duì)列中,如果有必要就喚醒目標(biāo)進(jìn)程。
  • 信號(hào)響應(yīng):進(jìn)程被喚醒后,根據(jù)信號(hào)隊(duì)列中的信息,調(diào)用信號(hào)回調(diào)函數(shù)。
我們?cè)賮?lái)看一下信號(hào)回調(diào)函數(shù),sa_handler的類型是__sihandler_t(include/asm-generic/singal.h),其定義為:
  1. typedef void __signalfn_t(int);  
  2. typedef __signalfn_t __user *__sighandler_t;  

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多