Nginx 부자 프로 세 스 생 성 및 주체 작업 함수

Nginx (0.7.67 버 전) 의 코드 에 따라 Nginx 기본 프로 세 스 생 성, 프로 세 스 주체 및 이벤트 처리 에 대해 간략하게 분석 하 였 습 니 다.
기본적으로 부모 프로 세 스 (즉 메 인 프로 세 스) 는 처음부터 설정 을 초기 화하 고 읽 으 며 각 모듈 의 기능 을 불 러 온 다음 에 fork () 에서 N 키 프로 세 스 (즉 작업 프로 세 스) 를 꺼 내 같은 작업 논리 와 기능 을 가지 고 있 습 니 다.부모 프로 세 스 는 신호 (예 를 들 어 HUP, QUIT 등) 를 감청 하고 socket pair 를 통 해 하위 프로 세 스에 신 호 를 전달 합 니 다 (하위 프로 세 스 간 에는 일반적으로 통신 하지 않 습 니 다).하위 프로 세 스 는 부모 프로 세 스 가 전달 하 는 신 호 를 이벤트 로 처리 합 니 다.모든 하위 프로 세 스 가 서비스 감청 포트 (예 를 들 어 http 80) 를 공유 하기 때문에 사용자 가 요청 을 보 낼 때 하위 프로 세 스 의 이벤트 호출 함 수 를 터치 합 니 다.따라서 accept () 요청 을 할 때 mutex 를 사용 하여 하나의 작업 프로 세 스 만 요청 을 받 아들 이 고 처리 할 수 있 도록 해 야 합 니 다.
Nginx 메 인 프로 세 스 의 입 구 는 일반적인 프로그램 과 같은 main () 함수 입 니 다. 코드 는 다음 과 같 습 니 다.
int ngx_cdecl main(int argc, char *const *argv)
{
	/*...*/

	//nginx                              id,
	//         ngx_listening_t    (   cycle->listening   ),
	//          getsockname,getsockopt                 
	//                 ngx_listening_t    ,          
	//         ,       ngx_init_cycle     

	if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { 
		return 1;								
	}

	/*...*/

	//ngx_modules   objs/ngx_modules.c  
	ngx_max_module = 0;
	for (i = 0; ngx_modules[i]; i++) {
		ngx_modules[i]->index = ngx_max_module++; //       
	}

	//ngx_init_cycle()  ,          , main, ngx_master_process_cycle
	// ngx_single_process_cycle   ,        reconfigure       。
	//      ,   cycle      cycle   ;    old cycle     , 
	//  log ,               ,   pool, shared mem, file handler, 
	//bind/listen socket ,       cycle   
	//              
	cycle = ngx_init_cycle(&init_cycle); 

	if (ngx_process == NGX_PROCESS_SINGLE) {
		ngx_single_process_cycle(cycle);
	} 
	else {	
		//           
		ngx_master_process_cycle(cycle);
	}
}
 
//ngx_start_worker_processes()  ,         n, ngx_worker_process_cycle() 
//      ngx_spawn_process()  work             ;
//          ngx_worker_process_cycle;          worker       
//worker     ;          (ngx_pass_open_channel())
//n worker process   
//type           , NGX_PROCESS_RESPAWN, NGX_PROCESS_JUST_RESPAWN
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{
	ngx_int_t      i;
	ngx_channel_t  ch;

	ch.command = NGX_CMD_OPEN_CHANNEL;

	for (i = 0; i < n; i++) {
		// config  CPU   
		cpu_affinity = ngx_get_cpu_affinity(i);
		//ngx_spawn_process   ngx_process_slot         
		//  slot
		ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
					"worker process", type);
		
		ch.pid = ngx_processes[ngx_process_slot].pid;
		ch.slot = ngx_process_slot;
		ch.fd = ngx_processes[ngx_process_slot].channel[0];
		//ngx_pass_open_channel    worker channel[0]   id
		//        slot  (ngx_write_channel())       
		//   worker。
		//  ,         ,  worker        worker 
		//channel[0] 
		ngx_pass_open_channel(cycle, &ch);
	}
}
 
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn)
{
	/*...*/
	//     NGX_PROCESS_DETACHED,         (          
	//        ),       socketpair。 
	if (respawn != NGX_PROCESS_DETACHED) {
		//  socketpair  
		//  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]     。  ,  worker      worker 
		//channel[0],  sendmsg(channel[0], ...)   worker    		
		/*...*/	
	}

	/*...*/
	//     
	pid = fork();
	switch (pid) {
		case -1:
			ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 
				"fork() failed while spawning "%s"", name);
			ngx_close_channel(ngx_processes[s].channel, cycle->log);
			return NGX_INVALID_PID;
		//     ,              
		case 0:
			ngx_pid = ngx_getpid();
			//  ngx_worker_process_cycle()
			//  :                  ,      
			//           
			proc(cycle, data);
			break;
		default:
			break;
	}
}
 
//worker     
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
	//        
	//       init_process    
	//      channel[1]  ,     
	//          ngx_processes  ,          channel[1]
	//    channel[0]  
	//     channel[0]       ,       sendmsg
	//  ngx_add_channel_event()  , ngx_channel           。
	ngx_worker_process_init(cycle, 1);
	//   ,    
	for ( ;; ) {
		
		/*...*/

		//  epoll,       
		//     (      ),         (  )
		//  accept queue event queue     
		ngx_process_events_and_timers(cycle);

		/*...*/
	}

	/*...*/
}
 

좋은 웹페이지 즐겨찾기