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

一文了解nginx中的signal處理機(jī)制

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

1. 引言

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

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

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

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

2. signal信號(hào)處理函數(shù)的注冊(cè)

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

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

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

下面是ngx_init_signals函數(shù)的實(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ù)中,對(duì)定義的signals數(shù)組進(jìn)行遍歷,并將對(duì)應(yīng)的signal處理函數(shù)注冊(cè)到操作系統(tǒng)中。

在注冊(cè)一個(gè)signal信號(hào)的時(shí)候,需要分幾步:

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

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

  • 如果不希望在處理當(dāng)前signal的時(shí)候block其他信號(hào),那么用sigemptyset清空sa_mask。

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

通過(guò)上面的循環(huán)遍歷,nginx注冊(cè)了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個(gè)信號(hào)。

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è)置信號(hào)阻塞

為了nginx在處理信號(hào)的過(guò)程中確保能夠正確地處理并且避免被中斷,需要對(duì)信號(hào)設(shè)置block阻塞標(biāo)記,從而能夠在處理指定信號(hào)的時(shí)候,避免新的信號(hào)進(jìn)來(lái)打擾處理過(guò)程。

在ngx_master_process_cycle函數(shù)(當(dāng)配置開啟了master_process模式時(shí)會(huì)作用master進(jìn)程的主循環(huán))的開頭部分,進(jì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);


這里對(duì)前面設(shè)置的10個(gè)信號(hào)(除了SIG_IGN)進(jìn)行了設(shè)置。

4. signal信號(hào)的處理

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

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

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

	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了,如果沒(méi)有設(shè)置,那么不執(zhí)行配置重加載的操作。

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

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

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

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

在nginx運(yùn)行的過(guò)程中,如果我們需要讓當(dāng)前的nginx能夠重新加載配置文件,我們可以在命令行輸入以下命令:

nginx -s reload

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

nginx -s stop

因?yàn)槲覀冊(cè)诿钚休斎胍陨厦畹臅r(shí)候,其實(shí)shell又重新啟動(dòng)了一個(gè)新的nginx進(jìn)程,那新的nginx進(jìn)程是如何通知正在提供服務(wù)的nginx進(jìn)程執(zhí)行相應(yīng)的動(dòng)作的呢?

這里就涉及到跨進(jìn)程信號(hào)發(fā)送的操作了。

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

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

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

意思就是向nginx進(jìn)程發(fā)送指定的信號(hào)。再看ngx_signal_process函數(shù)的實(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ù)對(duì)pid發(fā)送signal。由于linux/unix和windows的signal機(jī)制是不一樣的,所以ngx_os_signal_process函數(shù)針對(duì)兩類操作系統(tǒng)nginx進(jìn)行了單獨(dú)實(shí)現(xiàn),這里不再贅述。

6. 總結(jié)

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

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

相關(guān)文章

  • Nginx反向代理的主被動(dòng)健康檢查方式

    Nginx反向代理的主被動(dòng)健康檢查方式

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

    Nginx反向代理后臺(tái)報(bào)404遇到的解決方法

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

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

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

    Nginx 配置頁(yè)面請(qǐng)求不走緩存的方法

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

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

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

    淺談nginx基于請(qǐng)求頭或請(qǐng)求內(nèi)容的防護(hù)

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

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

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

    寶塔nginx部署前端頁(yè)面刷新報(bào)404錯(cuò)誤解決辦法

    使用nginx部署前端項(xiàng)目是一篇非常詳細(xì)的教程,旨在幫助初學(xué)者使用Nginx來(lái)部署前端項(xiàng)目,這篇文章主要給大家介紹了關(guān)于寶塔nginx部署前端頁(yè)面刷新報(bào)404錯(cuò)誤的解決辦法,需要的朋友可以參考下
    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)境

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

最新評(píng)論