nginx源碼分析—訊號初始化

來源:互聯網
上載者:User

作者:阿波
連結:http://blog.csdn.net/livelylittlefish/article/details/7308100

Content

0.序

1. ngx_init_signals()函數

1.1 ngx_signal_t結構

1.2 signals數組

1.3 sigaction結構

2.幾個問題

2.1ngx_signal_value宏是如何得到整數的訊號值signo的。

2.2 handler=SIG_IGN=0x1是如何忽略訊號的。

3.ngx_signal_handler()函數

4.小結

 

0.序

本文主要分析nginx訊號初始化及其處理。文中如無特別說明,.表示nginx-1.0.4代碼目錄,本文為/usr/src/nginx-1.0.4。

1. ngx_init_signals()函數

該函數主要任務是設定signals[]數組中每個訊號的action(即常說的註冊、安裝等)。如下。

./src/os/unix/ngx_process.c

ngx_int_tngx_init_signals(ngx_log_t *log){    ngx_signal_t      *sig;    struct sigaction   sa;    for (sig = signals; sig->signo != 0; sig++) {   /* signals數組 */        ngx_memzero(&sa, sizeof(struct sigaction)); /* 此處sigaction是一個結構類型 */        sa.sa_handler = sig->handler;        sigemptyset(&sa.sa_mask);    /* 清空sa_mask */        if (sigaction(sig->signo, &sa, NULL) == -1) { /* 設定sig->signo訊號的action,此處sigaction為系統API */            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,                          "sigaction(%s) failed", sig->signame);            return NGX_ERROR;        }    }    return NGX_OK;}

1.1 ngx_signal_t結構

nginx的訊號結構如下。

typedef struct {    int     signo;                /* 訊號值 */    char   *signame;              /* 訊號名 */    char   *name;                 /* 訊號可讀名 */    void  (*handler)(int signo);  /* 訊號處理常式 */} ngx_signal_t;

當nginx進程收到相關訊號時就會執行註冊的handler。

1.2 signals數組

對於該函數中的signals數組,其訊號的handler為ngx_signal_handler(),如下所示。

./src/os/unix/ngx_process.c

ngx_signal_t  signals[] = {    { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),      "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),      "reload",      ngx_signal_handler },    { ngx_signal_value(NGX_REOPEN_SIGNAL),      "SIG" ngx_value(NGX_REOPEN_SIGNAL),      "reopen",      ngx_signal_handler },    { ngx_signal_value(NGX_NOACCEPT_SIGNAL),      "SIG" ngx_value(NGX_NOACCEPT_SIGNAL),      "",      ngx_signal_handler },    { ngx_signal_value(NGX_TERMINATE_SIGNAL),      "SIG" ngx_value(NGX_TERMINATE_SIGNAL),      "stop",      ngx_signal_handler },    { ngx_signal_value(NGX_SHUTDOWN_SIGNAL),      "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),      "quit",      ngx_signal_handler },    { ngx_signal_value(NGX_CHANGEBIN_SIGNAL),      "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),      "",      ngx_signal_handler },    { SIGALRM, "SIGALRM", "", ngx_signal_handler },    { SIGINT, "SIGINT", "", ngx_signal_handler },    { SIGIO, "SIGIO", "", ngx_signal_handler },    { SIGCHLD, "SIGCHLD", "", ngx_signal_handler },    { SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN },    /* SIGSYS=31,該訊號handler=SIG_IGN,表示忽略該訊號 */    { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN },  /* SIGPIPE=13,該訊號handler=SIG_IGN,表示忽略該訊號 */     { 0, NULL, "", NULL }};

通過調試nginx,可以查看在運行環境中該數組的真實內容,也可看出ngx_signal_t結構,及nginx支援的訊號種類。如下。

(gdb) p signals$5 = {{    signo = 1,     signame = 0x476235 "SIGHUP",     name = 0x4726ab "reload",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 10,     signame = 0x47623c "SIGUSR1",     name = 0x4726a4 "reopen",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 28,     signame = 0x476244 "SIGWINCH",     name = 0x47b68f "",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 15,     signame = 0x47624d "SIGTERM",     name = 0x47269a "stop",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 3,     signame = 0x476255 "SIGQUIT",     name = 0x47269f "quit",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 12,     signame = 0x47625d "SIGUSR2",     name = 0x47b68f "",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 14,     signame = 0x476265 "SIGALRM",     name = 0x47b68f "",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 2,     signame = 0x47626d "SIGINT",     name = 0x47b68f "",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 29,     signame = 0x476274 "SIGIO",     name = 0x47b68f "",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 17,     signame = 0x47627a "SIGCHLD",     name = 0x47b68f "",     handler = 0x41df10 <ngx_signal_handler>  }, {    signo = 31,     signame = 0x476282 "SIGSYS, SIG_IGN",     name = 0x47b68f "",     handler = 0x1      /* 該訊號handler=SIG_IGN=0x1,表示忽略該訊號 */  }, {    signo = 13,     signame = 0x476292 "SIGPIPE, SIG_IGN",     name = 0x47b68f "",     handler = 0x1      /* 該訊號handler=SIG_IGN=0x1,表示忽略該訊號 */  }, {    signo = 0,     signame = 0x0,     name = 0x47b68f "",     handler = 0  }}

通過調試列印出signals數組的內容,可以很清晰地看到其定義。幾個用到的宏如下。

./src/core/ngx_config.h

#define ngx_signal_helper(n)     SIG##n#define ngx_signal_value(n)      ngx_signal_helper(n)#define NGX_SHUTDOWN_SIGNAL      QUIT#define NGX_TERMINATE_SIGNAL     TERM#define NGX_NOACCEPT_SIGNAL      WINCH#define NGX_RECONFIGURE_SIGNAL   HUP#if (NGX_LINUXTHREADS)#define NGX_REOPEN_SIGNAL        INFO#define NGX_CHANGEBIN_SIGNAL     XCPU#else#define NGX_REOPEN_SIGNAL        USR1#define NGX_CHANGEBIN_SIGNAL     USR2#endif

1.3 sigaction結構

sigaction結構定義如下。

struct sigaction {    void     (*sa_handler)(int);    void     (*sa_sigaction)(int, siginfo_t *, void *);    sigset_t   sa_mask;    int        sa_flags;    void     (*sa_restorer)(void);};

該定義從sigaction的manual頁而來,如果查看kernel原始碼,可能因版本不同有所調整。

 

2.幾個問題

2.1ngx_signal_value宏是如何得到整數的訊號值signo的。

 

舉個例子,NGX_RECONFIGURE_SIGNAL=HUP,因此ngx_signal_value(NGX_RECONFIGURE_SIGNAL)=SIGHUP。

從上述signals數組可以看出,SIGHUP的signo=1,name為"reload"。那麼,這個1是在哪裡定義的。

——這很容易能想到kernel原始碼。果期不然,在#include <signal.h>

 

file:/usr/include/asm/signal.h和/usr/include/asm-generic/signal.h均有定義。

#define SIGHUP 1#define SIGINT 2#define SIGQUIT 3#define SIGILL 4#define SIGTRAP 5#define SIGABRT 6#define SIGIOT 6#define SIGBUS 7#define SIGFPE 8#define SIGKILL 9#define SIGUSR110#define SIGSEGV11#define SIGUSR212#define SIGPIPE13#define SIGALRM14#define SIGTERM15#define SIGSTKFLT16#define SIGCHLD17#define SIGCONT18#define SIGSTOP19#define SIGTSTP20#define SIGTTIN21#define SIGTTOU22#define SIGURG23#define SIGXCPU24#define SIGXFSZ25#define SIGVTALRM26#define SIGPROF27#define SIGWINCH28#define SIGIO29#define SIGPOLLSIGIO/*#define SIGLOST29*/#define SIGPWR30#define SIGSYS31#defineSIGUNUSED31/* These should not be considered constants from userland.  */#define SIGRTMIN32#define SIGRTMAX_NSIG

2.2 handler=SIG_IGN=0x1是如何忽略訊號的。

從上述signals數組中可以看出,SIGSYS=31和SISPIPE=13訊號,其handler=SIG_IGN=0x1,表明忽略該訊號。是如何做到的。SIG_IGN又是在何處定義的。

 

file: /usr/include/asm-generic/signal-defs.h

#ifndef SIG_BLOCK#define SIG_BLOCK          0/* for blocking signals */#endif#ifndef SIG_UNBLOCK#define SIG_UNBLOCK        1/* for unblocking signals */#endif#ifndef SIG_SETMASK#define SIG_SETMASK        2/* for setting the signal mask */#endif#ifndef __ASSEMBLY__typedef void __signalfn_t(int);typedef __signalfn_t __user *__sighandler_t;typedef void __restorefn_t(void);typedef __restorefn_t __user *__sigrestore_t;#define SIG_DFL((__force __sighandler_t)0)/* default signal handling */#define SIG_IGN((__force __sighandler_t)1)/* ignore signal */#define SIG_ERR((__force __sighandler_t)-1)/* error return from signal */#endif

即,

#defineSIG_IGN((void (*)(int))1)

其handler函數類型為void(*)(int),符合sigaction結構中sa_handler定義。表明訊號忽略函數地址為1,而在實際中是不可能出現函數地址為1的情況,因此可用來區別於別的指標。

實際上,對nginx的31號和13號訊號,sigaction將SIG_IGN=0x1註冊(登記)為其signal的handler。即將這兩個訊號交給系統(init進程)處理。

另:忽略SIGCHLD訊號,常作為提高並發伺服器效能的一個技巧。因為並發伺服器可能fork很多子進程,子進程終結後需要伺服器處理序wait子進程並清理資源。如果將該訊號忽略,可使核心把殭屍子進程交給init進程處理,節省大量殭屍子進程佔用的系統資源。

 

3.ngx_signal_handler()函數

該函數僅根據其收到的訊號對相應的全域變數,如ngx_quit, ngx_terminate, ngx_noaccept等進行賦值(均賦值為1),當該進程發現相應變數為1時,即會採取相應的操作。

具體的處理,可參考原始碼。

 

4.小結

本文主要分析nginx啟動過程中訊號如何初始化。

 

Reference

# man sigaction

# man -S 7 signal

# man -S 2 kill

<Unix網路編程>

http://www.cplusplus.com/reference/clibrary/csignal/signal

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.