最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

1. 引言

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

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

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

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

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

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

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

這個調用的作用就是向操作系統(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ù)組進行遍歷,并將對應的signal處理函數(shù)注冊到操作系統(tǒng)中。

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

  • 初始化一個sigaction結構體。

  • 設置sigaction結構體中sa_sigaction或者sa_handler(二選一)至信號處理函數(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. 設置信號阻塞

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

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

    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);


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

4. signal信號的處理

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

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

譬如在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被設置為1了,如果沒有設置,那么不執(zhí)行配置重加載的操作。

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

再下來是調用ngx_init_cycle重新加載配置文件。

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

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

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

nginx -s reload

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

nginx -s stop

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

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

新啟動的進程根據(jù)命令行參數(shù),會讀取正在提供服務的nginx進程的pid文件,得到它的master進程的pid,然后調用系統(tǒng)函數(shù)kill來向master進程,這樣子master進程就會收到對應的信號,然后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文件,然后調用ngx_os_signal_process函數(shù)對pid發(fā)送signal。由于linux/unix和windows的signal機制是不一樣的,所以ngx_os_signal_process函數(shù)針對兩類操作系統(tǒng)nginx進行了單獨實現(xiàn),這里不再贅述。

6. 總結

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

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

相關文章

  • Nginx中使用Lua腳本配置示例

    Nginx中使用Lua腳本配置示例

    這篇文章主要介紹了Nginx中使用Lua腳本配置示例,本文以一個Lua攔截器為例講解如何配置使用Lua腳本,需要的朋友可以參考下
    2015-06-06
  • Nginx出現(xiàn)403錯誤,應該如何解決

    Nginx出現(xiàn)403錯誤,應該如何解決

    這篇文章主要介紹了Nginx出現(xiàn)403錯誤,應該如何解決?具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • NGINX報錯413 Request Entity Too Large的問題解決

    NGINX報錯413 Request Entity Too Large的問題解決

    Nginx 413錯誤表示請求實體太大,本文主要介紹了NGINX報錯413 Request Entity Too Large的問題解決,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • 在Linux和Windows系統(tǒng)上安裝Nginx服務器的教程

    在Linux和Windows系統(tǒng)上安裝Nginx服務器的教程

    這篇文章主要介紹了在Linux和Windows系統(tǒng)上安裝Nginx服務器的教程,Linux系統(tǒng)這里以CentOS為代表,需要的朋友可以參考下
    2015-08-08
  • 使用Nginx解決跨域訪問問題的完整案例

    使用Nginx解決跨域訪問問題的完整案例

    在現(xiàn)代的Web開發(fā)中,跨域訪問是一種常見的需求,由于瀏覽器的同源策略,不同域名之間的訪問存在一定的限制,本文將介紹如何使用Nginx來解決跨域訪問的問題,并通過一個完整的實例來展示,需要的朋友可以參考下
    2024-03-03
  • 滑塊驗證完整實現(xiàn)部署流程(前端?+?后端?+?Nginx?集成)

    滑塊驗證完整實現(xiàn)部署流程(前端?+?后端?+?Nginx?集成)

    滑塊驗證作為一種反機器人的工具,也會不斷發(fā)展和演進,以適應不斷變化的威脅,這篇文章主要介紹了滑塊驗證完整實現(xiàn)部署流程(前端?+?后端?+?Nginx集成)的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-12-12
  • nginx php-fpm中啟用慢日志配置(用于檢測執(zhí)行較慢的PHP腳本)

    nginx php-fpm中啟用慢日志配置(用于檢測執(zhí)行較慢的PHP腳本)

    這篇文章主要介紹了nginx php-fpm中啟用慢日志配置,php-fpm慢日志slowlog設置可以讓我們很好的看見哪些php進程速度太慢而導致的網(wǎng)站問題,可以讓我們方便的找到問題的所在,需要的朋友可以參考下
    2014-05-05
  • nginx 基本配置與參數(shù)說明詳細介紹

    nginx 基本配置與參數(shù)說明詳細介紹

    這篇文章主要介紹了nginx 基本配置與參數(shù)說明詳細介紹的相關資料,需要的朋友可以參考下
    2016-10-10
  • Nginx 安裝詳細教程

    Nginx 安裝詳細教程

    Nginx是一款自由的、開源的、高性能的HTTP服務器和反向代理服務器,這篇文章主要介紹了Nginx 安裝詳細教程,需要的朋友可以參考下
    2020-02-02
  • nginx日志導入elasticsearch的方法示例

    nginx日志導入elasticsearch的方法示例

    這篇文章主要介紹了nginx日志導入elasticsearch的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05

最新評論

巴彦县| 体育| 孝感市| 香河县| 淮滨县| 寻乌县| 咸丰县| 京山县| 介休市| 呼玛县| 闻喜县| 罗田县| 湟源县| 营山县| 丰城市| 东乌| 姚安县| 西平县| 凌源市| 宝鸡市| 全州县| 西丰县| 水富县| 巧家县| 商洛市| 合肥市| 建昌县| 蒙自县| 古浪县| 遂平县| 敖汉旗| 二手房| 沂水县| 北安市| 孟津县| 拉萨市| 辽阳市| 临城县| 南部县| 永福县| 呈贡县|