[nginx] nginx 소개 - 신호 처리
시그 널
master 가 worker 에 게 socketpair 를 통 해 제어 신 호 를 보 내 는 것 을 소개 할 때 어떤 신호 인지, 그리고 Liux 에서 어떻게 프로 세 스에 신 호 를 보 내 는 지 미리 소개 해 야 합 니 다.신호 에 대해 서 는 소프트웨어 프로 세 스 차원 에서 하 드 인 터 럽 트 에 대한 시 뮬 레이 션 이다.소프트웨어 차원 에서 중 단 된 처 리 를 할 수 없 지만 프로 세 스 간 의 통신 과 상호작용 이 필요 할 수도 있 습 니 다. 이때 신호 가 나타 납 니 다.프로 세 스 가 신 호 를 받 은 후에 몇 가지 다른 처리 방식 이 있 습 니 다. 신 호 를 무시 할 수 있 지만 두 가지 신 호 는 무시 할 수 없습니다. SIGKILL 과 SIGSTOP;처리 함 수 를 정의 하고 신호 가 도 착 했 을 때 처리 함 수 를 호출 하여 처리 합 니 다.결 성 된 작업 을 수행 하거나Liux 에서 신호 와 관련 된 주요 조작 함 수 는 다음 과 같은 kill, raise, alarm 과 setitimer, sigquue 함수 가 있 습 니 다.각 함수 시용 장소 도 다 르 고 기능 도 다 릅 니 다. 여기 서 kill 만 소개 합 니 다. nginx 에서 사용 하 는 kill 함수 가 보 내 는 신호 이기 때 문 입 니 다.
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
man 을 참고 하면 kill 은 모든 프로 세 스 (pid) 에 모든 신호 (sig) 를 보 낼 수 있 음 을 알 수 있 습 니 다.pid 에 따라 kill 이 보 내 는 신호 범위 도 다 릅 니 다. 관심 이 있 는 사람 은 Liux 의 시스템 함 수 를 보고 구체 적 인 사용 규범 을 알 수 있 습 니 다.
nginx 신호 처리
master 에 신 호 를 보 내 는 방식 은 nginx 가 제공 하 는 명령 도 구 를 사용 하 는 것 입 니 다.
nginx -s signal
현재 nginx 는 stop, quit, reopen, reload 몇 가지 신 호 를 지원 합 니 다.모든 신호 가 대표 하 는 의 미 는 사실 단어의 의 미 를 통 해 잘 이해 할 수 있 고 여기 서 상세 하 게 설명 하지 않 는 다.마스터 가 신 호 를 받 은 후에 nginx 가 어떤 조작 을 했 는 지 설명해 야 합 니 다.다음은 reload 프로필 이라는 명령 으로 소개 합 니 다.nginx 에 신 호 를 보 내 는 전 제 는 nginx 가 이미 시작 되 어야 합 니 다. 그러면 신 호 를 받 을 때 해당 하 는 조작 을 수행 할 수 있 습 니 다. 그렇지 않 으 면 잘못 보 고 될 것 입 니 다.신호 처리 와 관련 된 논 리 를 실행 할 때 파일 을 열 어야 하기 때문에 nginx 가 시작 하지 않 을 때 이 파일 들 은 존재 하지 않 기 때문에 파일 을 여 는 오류 가 발생 할 수 있 습 니 다.그 밖 에 nginx 가 시 작 된 후에 야 어떤 신 호 를 받 았 는 지 계속 감청 할 수 있 습 니 다.작 동 하지 않 으 면 시스템 이 어떻게 처리 해 야 할 지 전혀 모른다.따라서 nginx 의 신호 처리 에 대해 이야기 하려 면 nginx 의 시작 과정 을 조금 언급 해 야 합 니 다.이 글 은 nginx 시작 에 대해 상세 하 게 소개 하지 않 고 nginx 와 관련 된 신호 처리 부분 만 설명 합 니 다.nginx 는 main 함수 에서 관련 구조 체 초기 화 작업 을 한 다음 signals 초기 화 를 진행 합 니 다.
if (ngx_init_signals(cycle->log) != NGX_OK) {
return 1;
}
이 방법 은 이어서 ngx 를 호출 합 니 다.process. c 중 ngxinit_signals, 구체 적 인 방법 체:
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));
sa.sa_handler = sig->handler;
sigemptyset(&sa.sa_mask);
if (sigaction(sig->signo, &sa, NULL) == -1){
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "sigaction(%s) failed", sig->signame);
return NGX_ERROR;
}
}
return NGX_OK;
}
읽 기 편 하도록 비 핵심 논리 코드 를 삭제 했다.여기 서 볼 수 있 듯 이 이 방법 은 주로 모든 신호 의 처리 함 수 를 가리 키 는 데 사용 되 며, sigaction 을 통 해 모든 신호 가 올 때 어떤 방법 으로 처리 해 야 하 는 지 를 가리킨다.그 중에서 signals 는 nginx 가 정의 하 는 구조 체 의 배열 로 각 배열 의 대상 은 하나의 구조 체 이 고 이 구조 체 는 이 신호 의 명칭, 처리 방법 을 정의 하 며 구체 적 인 코드 는 다음 과 같다.
typedef struct {
int signo;
char *signame;
char *name;
void (*handler)(int signo);
} ngx_signal_t;
초기 화 신호 관련 작업 이 끝 난 후에 main 함수 가 계속 실 행 됩 니 다. 그 다음 에 master 프로 세 스 를 시작 할 지, single worker 를 시작 할 지 판단 에 따라 신호 처 리 는 master 시작 방법 에서 처 리 됩 니 다.
if (ngx_process == NGX_PROCESS_SINGLE) { ngx_single_process_cycle(cycle); } else { ngx_master_process_cycle(cycle); }
master 프로 세 스 를 시작 하기 전에 nginx 는 설정 파일 의 해석, 핵심 구조 체 의 초기 화, 로그 의 생 성 을 포함 하여 많은 작업 을 실 행 했 습 니 다.따라서 master 시작 방법 에 서 는 프로 세 스 이름 을 설정 하고 worker 프로 세 스 를 시작 한 다음 에 for (;) 순환 에 들 어 가 는 등 마무리 작업 을 실 행 했 습 니 다.사 순환 에 서 는 신호 와 신호 의 종류 가 있 는 지 끊임없이 검사 한 후 신호 에 따라 서로 다른 동작 을 한다.nginx 가 시 작 된 후에 우 리 는 nginx - s reload 를 입력 했 을 때 nginx 는 입력 한 매개 변 수 를 분석 한 결과 신 호 를 전달 한 것 을 발견 하고 다음 에 ngx 를 실행 합 니 다.signal_process 방법, 그리고 return.이 방법 은 nginx 의 생명주기 구조 체 cycle (이 구조 체 를 어떻게 해석 해 야 할 지 모 르 겠 음) 과 신호 의 이름 을 받아들인다.이 방법 은 해당 논 리 를 판단 한 후 ngx 를 호출 합 니 다.process. c 의 방법 ngxos_signal_process。nginx 에서 모든 프로 세 스 작업 은 이 파일 에서 프로 세 스 를 생 성, 죽 이 는 방법 을 제공 합 니 다.위의 이 방법 에 대해 사실은 Liux 의 시스템 호출 kill 을 호출 한 것 입 니 다. 방법 은 다음 과 같 습 니 다.
int kill(pid_t pid, int sig)
들 어 오 는 nginx 의 pid 와 구체 적 인 신 호 를 통 해 master 에 게 해당 하 는 신호 에 따라 지정 한 작업 을 수행 하 라 고 알려 줍 니 다.핵심 논리 코드 는 다음 과 같 고 코드 가 비교적 길 며 사실은 각종 판정 이 며 서로 다른 신호 에 따라 서로 다른 처 리 를 한다.
for ( ;; ) {
if (delay) {
if (ngx_sigalrm) {
sigio = 0;
delay *= 2;
ngx_sigalrm = 0;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"termination cycle: %d", delay);
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = delay / 1000;
itv.it_value.tv_usec = (delay % 1000 ) * 1000;
if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"setitimer() failed");
}
}
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend");
sigsuspend(&set);
ngx_time_update();
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"wake up, sigio %i", sigio);
if (ngx_reap) {
ngx_reap = 0;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");
live = ngx_reap_children(cycle);
}
if (!live && (ngx_terminate || ngx_quit)) {
ngx_master_process_exit(cycle);
}
if (ngx_terminate) {
if (delay == 0) {
delay = 50;
}
if (sigio) {
sigio--;
continue;
}
sigio = ccf->worker_processes + 2 /* cache processes */;
if (delay > 1000) {
ngx_signal_worker_processes(cycle, SIGKILL);
} else {
ngx_signal_worker_processes(cycle,
ngx_signal_value(NGX_TERMINATE_SIGNAL));
}
continue;
}
if (ngx_quit) {
ngx_signal_worker_processes(cycle,
ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
ls = cycle->listening.elts;
for (n = 0; n < cycle->listening.nelts; n++) {
if (ngx_close_socket(ls[n].fd) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_close_socket_n " %V failed",
&ls[n].addr_text);
}
}
cycle->listening.nelts = 0;
continue;
}
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));
}
if (ngx_restart) {
ngx_restart = 0;
ngx_start_worker_processes(cycle, ccf->worker_processes,
NGX_PROCESS_RESPAWN);
ngx_start_cache_manager_processes(cycle, 0);
live = 1;
}
if (ngx_reopen) {
ngx_reopen = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
ngx_reopen_files(cycle, ccf->user);
ngx_signal_worker_processes(cycle,
ngx_signal_value(NGX_REOPEN_SIGNAL));
}
if (ngx_change_binary) {
ngx_change_binary = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary");
ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv);
}
if (ngx_noaccept) {
ngx_noaccept = 0;
ngx_noaccepting = 1;
ngx_signal_worker_processes(cycle,
ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
}
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA- 소스 코드 분할(Package 사용)▪️test45.java 소스 코드 ▪️test47.java 소스 코드 ▪️실행 결과 더하면 12, 당기면 8 ▪️예① 클래스 이름에 대한 완전한 입력 생략 import 문 사용 ▪️예① test45.java 소스 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.