欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文了解nginx中的signal處理機制

 更新時間:2024年05月31日 09:21:50   作者:碼農(nóng)心語  
nginx利用信號處理機制,可以捕獲和處理各種信號,本文主要介紹了nginx中的signal處理機制,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1. 引言

在計算機系統(tǒng)中,信號處理是一項重要的任務(wù),它允許操作系統(tǒng)和應(yīng)用程序之間進行通信和協(xié)調(diào)。在網(wǎng)絡(luò)服務(wù)器軟件中,如Nginx,信號處理機制起著關(guān)鍵作用,它能夠捕獲和處理各種類型的信號,從而實現(xiàn)服務(wù)器的靈活控制和運行時的動態(tài)行為。

nginx是一款高性能、輕量級的Web服務(wù)器和反向代理服務(wù)器,被廣泛應(yīng)用于構(gòu)建可靠、高效的Web應(yīng)用程序和服務(wù)。為了滿足各種需求和應(yīng)對不同的運行時情況,nginx提供了豐富的信號處理機制,使得管理員和開發(fā)人員能夠通過發(fā)送信號來實現(xiàn)對服務(wù)器的管理和控制。

信號是一種在操作系統(tǒng)中用于通知進程發(fā)生某種事件或請求某種操作的機制。它可以用于向進程發(fā)送中斷信號、終止信號、重啟信號等,以及自定義的應(yīng)用程序信號。nginx利用信號處理機制,可以捕獲和處理各種信號,例如重新加載配置文件、優(yōu)雅地停止或重啟服務(wù)器等。

深入理解nginx中的信號處理機制需要了解信號的基本概念和操作系統(tǒng)對信號的支持。當nginx接收到一個信號時,它會根據(jù)信號的類型和當前的運行狀態(tài)執(zhí)行相應(yīng)的操作。例如,當接收到重新加載配置文件的信號時,nginx會重新讀取配置文件并應(yīng)用新的配置,而不需要重啟整個服務(wù)器。

2. signal信號處理函數(shù)的注冊

在nginx的main函數(shù)中有一個函數(shù)調(diào)用,如下:

    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

這個調(diào)用的作用就是向操作系統(tǒng)注冊當前進程的signal處理函數(shù)。

下面是ngx_init_signals函數(shù)的實現(xiàn)源碼:

ngx_int_t
ngx_init_signals(ngx_log_t *log)
{
    ngx_signal_t   *sig;
    struct sigaction   sa;

    for (sig = signals; sig->signo != 0; sig++) {
        ngx_memzero(&sa, sizeof(struct sigaction));

        if (sig->handler) {
            sa.sa_sigaction = sig->handler;
            sa.sa_flags = SA_SIGINFO;

        } else {
            sa.sa_handler = SIG_IGN;
        }

        sigemptyset(&sa.sa_mask);
        if (sigaction(sig->signo, &sa, NULL) == -1) {
#if (NGX_VALGRIND)
            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                          "sigaction(%s) failed, ignored", sig->signame);
#else
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                          "sigaction(%s) failed", sig->signame);
            return NGX_ERROR;
#endif
        }
    }

    return NGX_OK;
}

在ngx_init_signals函數(shù)中,對定義的signals數(shù)組進行遍歷,并將對應(yīng)的signal處理函數(shù)注冊到操作系統(tǒng)中。

在注冊一個signal信號的時候,需要分幾步:

  • 初始化一個sigaction結(jié)構(gòu)體。

  • 設(shè)置sigaction結(jié)構(gòu)體中sa_sigaction或者sa_handler(二選一)至信號處理函數(shù)。對于前者,需要設(shè)置sa_flags = SA_SIGINFO。

  • 如果不希望在處理當前signal的時候block其他信號,那么用sigemptyset清空sa_mask。

  • 最后,通過sigaction向操作系統(tǒng)注冊消息處理函數(shù)。

通過上面的循環(huán)遍歷,nginx注冊了SIGHUP(reload)、SIGUSR1(reopen)、SIGWINCH(noaccept)、SIGTERM(stop)、SIGQUIT(quit)、SIGUSR2(change bin)、SIGARLRM(timer)、SIGINT(stop)、SIGIO()、SIGCHLD(child reap)、SIGSYS(ignore)、SIGPIPE(ignore)共12個信號。

signals的定義如下:

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", "", NULL },

    { SIGPIPE, "SIGPIPE, SIG_IGN", "", NULL },

    { 0, NULL, "", NULL }
};

3. 設(shè)置信號阻塞

為了nginx在處理信號的過程中確保能夠正確地處理并且避免被中斷,需要對信號設(shè)置block阻塞標記,從而能夠在處理指定信號的時候,避免新的信號進來打擾處理過程。

在ngx_master_process_cycle函數(shù)(當配置開啟了master_process模式時會作用master進程的主循環(huán))的開頭部分,進行了相關(guān)設(shè)置,源碼如下:

    sigemptyset(&set);
    sigaddset(&set, SIGCHLD);
    sigaddset(&set, SIGALRM);
    sigaddset(&set, SIGIO);
    sigaddset(&set, SIGINT);
    sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
    sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));

    if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "sigprocmask() failed");
    }

    sigemptyset(&set);


這里對前面設(shè)置的10個信號(除了SIG_IGN)進行了設(shè)置。

4. signal信號的處理

在nginx中,signal信號是由ngx_signal_handler函數(shù)負責接收處理的。不過,ngx_signal_handler函數(shù)對信號的處理其實就是對應(yīng)接收到的信號設(shè)置相應(yīng)的標記,然后立即返回。譬如收到SIGTERM信號,則設(shè)置ngx_terminate = 1,收到SIGHUP信號,則設(shè)置ngx_reconfigure等等。其自己本身不進行實際的信號處理。

signal信號的處理邏輯是在主循環(huán)中進行的。如果是master/worker多進程運行模式下,在ngx_master_process_cycle函數(shù)中處理,如果是單進程運行模式下,則是在ngx_single_process_cycle函數(shù)中進行處理。在主循環(huán)函數(shù)中,它會檢查ngx_signal_handler中設(shè)置的標記位,然后根據(jù)各個標記位進行對應(yīng)的處理。

譬如在ngx_master_process_cycle函數(shù)中對配置重加載信號的處理邏輯如下:

	if (ngx_reconfigure) {
		ngx_reconfigure = 0;

		if (ngx_new_binary) {
			ngx_start_worker_processes(cycle, ccf->worker_processes,
									   NGX_PROCESS_RESPAWN);
			ngx_start_cache_manager_processes(cycle, 0);
			ngx_noaccepting = 0;

			continue;
		}

		ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring");

		cycle = ngx_init_cycle(cycle);
		if (cycle == NULL) {
			cycle = (ngx_cycle_t *) ngx_cycle;
			continue;
		}

		ngx_cycle = cycle;
		ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
											   ngx_core_module);
		ngx_start_worker_processes(cycle, ccf->worker_processes,
								   NGX_PROCESS_JUST_RESPAWN);
		ngx_start_cache_manager_processes(cycle, 1);

		/* allow new processes to start */
		ngx_msleep(100);

		live = 1;
		ngx_signal_worker_processes(cycle,
									ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
	}

首先它判斷是否ngx_reconfigure被設(shè)置為1了,如果沒有設(shè)置,那么不執(zhí)行配置重加載的操作。

接著,如果是正在更新二進制文件操作,即ngx_new_binary=1,那么需要在這里啟動新的worker進程和cache manager進程。

再下來是調(diào)用ngx_init_cycle重新加載配置文件。

加載新的worker進程,最后通知老的worker進程進行優(yōu)雅退出。

5. 跨進程發(fā)送signal

在nginx運行的過程中,如果我們需要讓當前的nginx能夠重新加載配置文件,我們可以在命令行輸入以下命令:

nginx -s reload

又或者,如果我們希望停止nginx運行,我們可以在命令行輸入一下命令:

nginx -s stop

因為我們在命令行輸入以上命令的時候,其實shell又重新啟動了一個新的nginx進程,那新的nginx進程是如何通知正在提供服務(wù)的nginx進程執(zhí)行相應(yīng)的動作的呢?

這里就涉及到跨進程信號發(fā)送的操作了。

新啟動的進程根據(jù)命令行參數(shù),會讀取正在提供服務(wù)的nginx進程的pid文件,得到它的master進程的pid,然后調(diào)用系統(tǒng)函數(shù)kill來向master進程,這樣子master進程就會收到對應(yīng)的信號,然后master主循環(huán)函數(shù)就會進行信號的處理。

在main函數(shù)中,我們可以看到下面的代碼:

    if (ngx_signal) {
        return ngx_signal_process(cycle, ngx_signal);
    }

意思就是向nginx進程發(fā)送指定的信號。再看ngx_signal_process函數(shù)的實現(xiàn):

ngx_int_t
ngx_signal_process(ngx_cycle_t *cycle, char *sig)
{
    ssize_t           n;
    ngx_pid_t         pid;
    ngx_file_t        file;
    ngx_core_conf_t  *ccf;
    u_char            buf[NGX_INT64_LEN + 2];

    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started");

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    ngx_memzero(&file, sizeof(ngx_file_t));

    file.name = ccf->pid;
    file.log = cycle->log;

    file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
                            NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS);

    if (file.fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", file.name.data);
        return 1;
    }

    n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0);

    if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", file.name.data);
    }

    if (n == NGX_ERROR) {
        return 1;
    }

    while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ }

    pid = ngx_atoi(buf, ++n);

    if (pid == (ngx_pid_t) NGX_ERROR) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
                      "invalid PID number \"%*s\" in \"%s\"",
                      n, buf, file.name.data);
        return 1;
    }

    return ngx_os_signal_process(cycle, sig, pid);

}

非常好理解,就是讀取pid文件,然后調(diào)用ngx_os_signal_process函數(shù)對pid發(fā)送signal。由于linux/unix和windows的signal機制是不一樣的,所以ngx_os_signal_process函數(shù)針對兩類操作系統(tǒng)nginx進行了單獨實現(xiàn),這里不再贅述。

6. 總結(jié)

以上通過對nginx的源碼分析,從signal信號的注冊和阻塞狀態(tài)設(shè)置,到signal信號的處理,最后到跨進程singla信號的發(fā)送進行了詳細的介紹,我們可以從中一窺nginx如何利用操作系統(tǒng)的signal機制來實現(xiàn)對進程的各種控制功能。

到此這篇關(guān)于一文了解nginx中的signal處理機制的文章就介紹到這了,更多相關(guān)nginx signal 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Nginx反向代理的主被動健康檢查方式

    Nginx反向代理的主被動健康檢查方式

    這篇文章主要介紹了Nginx反向代理的主被動健康檢查方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Nginx反向代理后臺報404遇到的解決方法

    Nginx反向代理后臺報404遇到的解決方法

    Nginx反向代理404錯誤通常是由服務(wù)器配置不正確、文件路徑不正確、文件權(quán)限不正確、文件名大小寫不正確等,本文主要介紹了Nginx反向代理后臺報404遇到的解決方法,感興趣的可以了解一下
    2023-11-11
  • prometheus監(jiān)控nginx的兩種方式

    prometheus監(jiān)控nginx的兩種方式

    這篇文章主要介紹了兩種不同的Nginx監(jiān)控方法,第一種是nginx自帶的tub_status模塊進行監(jiān)控,第二種是用vts監(jiān)控工具進行監(jiān)控,都是基于prometheus、grafana結(jié)合第三方模塊或監(jiān)控工具搭建,文中通過圖文結(jié)合的方式介紹的非常詳細,需要的朋友可以參考下
    2024-05-05
  • Nginx 配置頁面請求不走緩存的方法

    Nginx 配置頁面請求不走緩存的方法

    在Nginx中配置禁止緩存內(nèi)容,可通過設(shè)置HTTP響應(yīng)頭中的緩存控制指令實現(xiàn),全局禁用緩存可在http或server上下文中添加特定的add_header指令,本文就來詳細的介紹一下,感興趣的可以了解一下
    2024-11-11
  • Nginx+Keepalived實現(xiàn)雙機主備的方法

    Nginx+Keepalived實現(xiàn)雙機主備的方法

    這篇文章主要介紹了Nginx+Keepalived實現(xiàn)雙機主備的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • 淺談nginx基于請求頭或請求內(nèi)容的防護

    淺談nginx基于請求頭或請求內(nèi)容的防護

    本文主要介紹了淺談nginx基于請求頭或請求內(nèi)容的防護,通常涉及到對請求進行過濾,檢查其是否包含某些特定的值或模式,感興趣的可以了解一下
    2023-10-10
  • 詳解Nginx 靜態(tài)文件服務(wù)配置及優(yōu)化

    詳解Nginx 靜態(tài)文件服務(wù)配置及優(yōu)化

    這篇文章主要介紹了Nginx 靜態(tài)文件服務(wù)配置及優(yōu)化,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • 寶塔nginx部署前端頁面刷新報404錯誤解決辦法

    寶塔nginx部署前端頁面刷新報404錯誤解決辦法

    使用nginx部署前端項目是一篇非常詳細的教程,旨在幫助初學者使用Nginx來部署前端項目,這篇文章主要給大家介紹了關(guān)于寶塔nginx部署前端頁面刷新報404錯誤的解決辦法,需要的朋友可以參考下
    2024-03-03
  • 結(jié)合 Nginx 將 DoNetCore 部署到 阿里云的安裝配置方法

    結(jié)合 Nginx 將 DoNetCore 部署到 阿里云的安裝配置方法

    這篇文章主要介紹了結(jié)合 Nginx 將 DoNetCore 部署到 阿里云的方法 ,需要的朋友可以參考下
    2018-10-10
  • nginx+apache+mysql+php+memcached+squid搭建集群web環(huán)境

    nginx+apache+mysql+php+memcached+squid搭建集群web環(huán)境

    當前,LAMP開發(fā)模式是WEB開發(fā)的首選,如何搭建一個高效、可靠、穩(wěn)定的WEB服務(wù)器一直是個熱門主題,本文就是這個主題的一次嘗試。
    2011-03-03

最新評論