nginx 소스 학습 노트 (17) - ngxworker_process_cycle 서브 프로 세 스 실행
src/os/unix/ngx_process_cycle.c
static void
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
ngx_uint_t i;
ngx_connection_t *c;
// master ,ngx_process NGX_PROCESS_MASTER
ngx_process = NGX_PROCESS_WORKER;
//
ngx_worker_process_init(cycle, 1);
ngx_setproctitle("worker process");
#if (NGX_THREADS)
//
#endif
for ( ;; ) {
// ,
if (ngx_exiting) {
c = cycle->connections;
for (i = 0; i < cycle->connection_n; i++) {
/* THREAD: lock */
if (c[i].fd != -1 && c[i].idle) {
c[i].close = 1;
c[i].read->handler(c[i].read);
}
}
if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel)
{
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
ngx_worker_process_exit(cycle);
}
}
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle");
//
ngx_process_events_and_timers(cycle);
// NGX_CMD_TERMINATE
if (ngx_terminate) {
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting");
// , exit_process
ngx_worker_process_exit(cycle);
}
// NGX_CMD_QUIT
if (ngx_quit) {
ngx_quit = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
"gracefully shutting down");
ngx_setproctitle("worker process is shutting down");
// " "
if (!ngx_exiting) {
// socket,
ngx_close_listening_sockets(cycle);
ngx_exiting = 1;
}
}
// NGX_CMD_REOPEN , log
if (ngx_reopen) {
ngx_reopen = 0;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
ngx_reopen_files(cycle, -1);
}
}
}
프로 세 스 초기 화 작업 을 살 펴 보 겠 습 니 다.
1. 전역 적 인 설정, 전역 적 인 설정 정보 설정 에 따라 실행 환경, 우선 순위, 제한, setgid, setuid, 신호 초기 화 등;
2. 모든 모듈 의 갈고리 init 호출process;
src/os/unix/ngx_process_cycle.c
for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->init_process) {
if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
/* fatal */
exit(2);
}
}
}
3. 사용 하지 않 는 socket 을 닫 고 현재 worker 의 channel [0] 핸들 과 다른 worker 의 channel [1] 핸들 을 닫 습 니 다. 현재 worker 는 다른 worker 의 channel [0] 핸들 로 메 시 지 를 보 냅 니 다. 현재 worker 의 channel [1] 핸들 로 읽 을 수 있 는 이 벤트 를 감청 합 니 다.
src/os/unix/ngx_process_cycle.c
for (n = 0; n < ngx_last_process; n++) {
// worker
if (ngx_processes[n].pid == -1) {
continue;
}
if (n == ngx_process_slot) {
continue;
}
if (ngx_processes[n].channel[1] == -1) {
continue;
}
// worker channel[1] ( )
if (close(ngx_processes[n].channel[1]) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"close() channel failed");
}
}
// channel[0] ( )
if (close(ngx_processes[ngx_process_slot].channel[0]) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"close() channel failed");
}
// , worker channel[0]
// worker channel[1]
4. 현재 worker 의 channel [1] 핸들 에서 읽 을 수 있 는 이 벤트 를 감청 합 니 다.
if (ngx_add_channel_event(cycle, ngx_channel, NGX_READ_EVENT,
ngx_channel_handler)
== NGX_ERROR)
{
/* fatal */
exit(2);
}
ngx_add_channel_이벤트 핸들 ngxchannel (현재 worker 의 channel [1]) 에 연 결 된 읽 기 가능 한 이벤트 가 이벤트 모니터링 대기 열 에 추가 되 었 습 니 다. 이벤트 처리 함 수 는 ngx 입 니 다.channel_hanlder(ngx_event_t *ev)。읽 을 수 있 는 이벤트 가 있 을 때, ngxchannel_handler 는 메 시 지 를 처리 하고 구체 적 인 코드 는 src / os / unix / ngx 를 볼 수 있 습 니 다.channel. c, 과정 은 다음 과 같 습 니 다.
src/os/unix/ngx_process_cycle.c
static void
ngx_channel_handler(ngx_event_t *ev)
{
ngx_int_t n;
ngx_channel_t ch;
ngx_connection_t *c;
if (ev->timedout) {
ev->timedout = 0;
return;
}
c = ev->data;
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel handler");
for ( ;; ) {
// channel[1]
n = ngx_read_channel(c->fd, &ch, sizeof(ngx_channel_t), ev->log);
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
if (n == NGX_ERROR) {
if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
ngx_del_conn(c, 0);
}
ngx_close_connection(c);
return;
}
if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {
if (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
return;
}
}
if (n == NGX_AGAIN) {
return;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
"channel command: %d", ch.command);
//
switch (ch.command) {
case NGX_CMD_QUIT:
ngx_quit = 1;
break;
case NGX_CMD_TERMINATE:
ngx_terminate = 1;
break;
case NGX_CMD_REOPEN:
ngx_reopen = 1;
break;
case NGX_CMD_OPEN_CHANNEL:
ngx_log_debug3(NGX_LOG_DEBUG_CORE, ev->log, 0,
"get channel s:%i pid:%P fd:%d",
ch.slot, ch.pid, ch.fd);
ngx_processes[ch.slot].pid = ch.pid;
ngx_processes[ch.slot].channel[0] = ch.fd;
break;
case NGX_CMD_CLOSE_CHANNEL:
ngx_log_debug4(NGX_LOG_DEBUG_CORE, ev->log, 0,
"close channel s:%i pid:%P our:%P fd:%d",
ch.slot, ch.pid, ngx_processes[ch.slot].pid,
ngx_processes[ch.slot].channel[0]);
if (close(ngx_processes[ch.slot].channel[0]) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"close() channel failed");
}
ngx_processes[ch.slot].channel[0] = -1;
break;
}
}
}
요약: 정리 하기 전에 한 학생 에 게 이 절 과 지난 절의 내용 과 코드 를 읽 어 주 고 싶 습 니 다.
총 결http://blog.csdn.net/lu_ming/article/details/5151930 작가 의 사심 없 는 헌신 에 감사 드 립 니 다.
1. ngx_start_worker_processes () 함수, 이 함 수 는 지 정 된 수량 n 에 따라 ngx 로worker_process_cycle () 함수 매개 변수 호출 ngxspawn_process () 는 work 프로 세 스 를 만 들 고 관련 자원 과 속성 을 초기 화 합 니 다.하위 프로 세 스 실행 함수 ngxworker_process_cycle;이전에 만 든 모든 워 커 에 게 현재 만 든 워 커 프로 세 스 의 정 보 를 방송 합 니 다.프로 세 스 마다 채널 을 엽 니 다 (ngx pass open channel (). ngx_start_worker_processes () 함수 의 주요 논 리 는 다음 과 같다. a) 먼저 설명 하고 자 하 는 것 은 인자 respawn 은 두 가지 의미 가 있 습 니 다. type 은 NGX 와 같은 새로운 프로 세 스 방식 을 만 드 는 것 입 니 다.PROCESS_RESPAWN, NGX_PROCESS_JUST_RESPAWN... 마이너스 입 니 다.다른 하 나 는 프로 세 스 정보 표 의 아래 표 시 를 표시 합 니 다. 이 때 는 마이너스 입 니 다. b) 찾기 ngxprocesses [] 프로 세 스 정보 표 의 빈 항목; c) 분 리 된 하위 프로 세 스 가 아니라면 (respawn! = NGX PROCESS DETACHED), i) 연 결 된 이름 없 는 socket 만 들 기; ii) socket (channel [0] 과 channel [1]) 을 비 차단 모드 로 설정 합 니 다. iii) 채널 [0] 메시지 구동 IO 열기; iv) 채널 [0] 의 속 주 를 설정 하고 채널 [0] 의 SIGIO 신 호 를 이 프로 세 스 에 만 보 냅 니 다. v) 채널 [0] 과 채널 [1] 의 FD 설정CLOEXEC 속성 (프로 세 스 가 exec 를 실행 한 후 socket 을 닫 습 니 다); vi) 읽 을 수 있 는 이 벤트 를 감청 하 는 socket (즉, ngx channel = ngx processes [s]. channel [1];) 을 가 져 옵 니 다. d) 분 리 된 하위 프로 세 스 시, ngxprocesses[s].channel[0] = -1; ngx_processes[s].channel[1] = -1; e) 현재 하위 프로 세 스 의 프로 세 스 표 항목 인덱스 설정 하기;ngx_process_slot = s; f) 하위 프로 세 스 만 들 기; g) 하위 프로 세 스 식 에서 현재 하위 프로 세 스 의 프로 세 스 id 를 설정 하고 실행 함 수 를 실행 합 니 다. h) respawn > = 0 시 pid 를 직접 되 돌려 줍 니 다. i) 다른 프로 세 스 표 항목 필드 설정 하기; ngx_processes[s].proc = proc; ngx_processes[s].data = data; ngx_processes[s].name = name; ngx_processes[s].exiting = 0; j) respawn 이 표시 하 는 유형 에 따라 표 항목 을 다른 방식 으로 설정 합 니 다.
socketpair 를 만 드 는 것 은 프로 세 스 간 통신 에 사 용 됩 니 다. master 프로 세 스 는 모든 worker 에 socket 을 만 듭 니 다. master 프로 세 스 공간 은 모든 socketpair 의 channel [0], channel [1] 양 끝 핸들 을 엽 니 다.worker 를 만 들 때 이 worker 는 master 가 현재 만 들 고 열 린 모든 socketpair 를 계승 합 니 다. 이 worker 가 초기 화 될 때 (ngx worker process init 호출) 이 프로 세 스 가 socketpair 에 대응 하 는 channel [0] 과 다른 worker 에 대응 하 는 channel [1] 을 닫 고 이 프로 세 스 가 socketpair 에 대응 하 는 channel [1] 을 열 고 다른 worker 와 대응 하 는 channel [0] 을 유지 합 니 다.이 프로 세 스 가 socketpair 에 대응 하 는 channel [1] 의 읽 을 수 있 는 이 벤트 를 감청 합 니 다.이렇게 하면 모든 워 커 는 다른 워 커 의 채널 [0] 을 가지 고 있 으 며, sendmsg (channel [0],...) 는 다른 워 커 에 게 메 시 지 를 보 낼 수 있 습 니 다. 현재 worker 가 만 든 worker 보다 먼저 상속 을 통 해 channel [0] 을 얻 었 습 니 다. 그러나 그 후에 만 든 프로 세 스 의 channel [0] 을 어떻게 얻 을 수 있 습 니까? 답 은 위 (ngx start worker processes) master 에서 worker 를 만 들 고 시작 한 후에 ngx pass open channel 을 호출 하여 이 worker 의 channel [0] 과 프로 세 스 id, 프로 세 스 표 에서 의 오프셋 slot 방송 을 호출 합 니 다.(ngx write channel () 은 이미 만 든 모든 worker 에 게 모든 프로 세 스 를 만 든 후에 모든 worker 는 다른 worker 의 channel [0] 을 얻 었 습 니 다. ngx worker process cycle () 함 수 는 모든 프로 세 스 의 실제 작업 내용 입 니 다. 이 함수 에 서 는 먼저 ngx create thread () 를 호출 하여 각 스 레 드 를 초기 화 합 니 다. 스 레 드 마다 시작 처리 함수 가 있다 는 것 을 알 고 있 습 니 다. ngx 의 스 레 드 처리 함 수 는 ngx worker thread cycle () 입 니 다. 내부 과정 에서 가장 중요 한 것 은 ngx event thread process posted () 입 니 다.함수 호출 은 모든 요청 을 실제 처리 하 는 데 사 용 됩 니 다. 초기 화 스 레 드 가 끝 난 후 먼저 ngx process events and timers () 함 수 를 호출 합 니 다. 이 함 수 는 ngx process events 인터페이스 감청 사건 을 계속 호출 합 니 다. 일반적인 상황 에서 대응 하 는 함 수 는 ngx epoll process events () 입 니 다.이 인 터 페 이 스 는 ngx posted events 이벤트 대기 열 에 사건 을 배달 하고 ngx event thread process posted () 함수 에서 처리 합 니 다.
2. ngx start cache manager processes () 함수 입 니 다. 이 함 수 는 ngx cycle 전역 대상 의 path 배열 에서 manager 와 loader 함수 가 있 는 지 확인 합 니 다. manage 함수 가 있 으 면 버퍼 관리 프로 세 스 를 만 들 고 해당 채널 을 열 어 불 러 오 는 작업 을 담당 합 니 다. loader 함수 가 있 으 면 버퍼 관리 프로 세 스 를 만 들 고 해당 채널 을 열 어 불 러 옵 니 다. 3. ngx pass open channel () 함수 입 니 다. 이 함 수 는 전체 ngx processes 배열 에 있 는 모든 pid 가 - 1 이 아 닙 니 다. channel [0] 은 - 1 프로 세 스 에 채널 을 열지 않 습 니 다. 즉, 만 든 모든 work 프로 세 스 에 채널 을 열 고 메시지 (ngx write channel () 를 작업 프로 세 스에 보 냅 니 다. 4. ngx signal worker processes () 함수 입 니 다. 이 함 수 는 주로 각 work 프로 세 스에 신 호 를 보 냅 니 다. ngx signal value (NGX REOPEN SIGNAL) 신호 라면 ngx processes 의 플래그 exiting 을 1 로 설정 합 니 다. 5. ngx reap children () 함수 입 니 다. 이 함 수 는 종료 할 프로 세 스 를 정리 합 니 다. ngx processes 배열 에 있 는 항목 마다 프로 세 스 에 대응 하 는 신 호 를 저장 합 니 다. pid, status, channel 등 이 있 습 니 다. 하위 프로 세 스 가 exiting 이나! detached 를 종료 하지 않 았 다 면 live 는 1 로 설정 합 니 다. ngx master process exit () 함수, 이 함수 가 pid 파일 을 삭제 한 다음 모듈 에 있 는 exit master 갈고리 함 수 를 호출 하여 메모리 풀 을 소각 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Exception in thread main java.lang. NoClassDefFoundError 오류 해결 방법즉,/home/hadoop/jarfile) 시스템은 Hello World 패키지 아래의class라는 클래스 파일을 실행하고 있다고 오인하여 시스템의 CLASSPATH 아래 (일반적으로 현재 디렉터리를 포함) Hell...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.