Nginx 소스 코드 분석 - 주류 프로 세 스 - Nginx 의 시작 프로 세 스

13691 단어
앞의 몇 편 은 주로 Nginx 가 비교적 자주 사용 하 는 기초 데이터 구 조 를 소개 했다. 예 를 들 어 pool, buf, array, list 등 이다.Nginx 기초 데이터 구조 에 대한 이 해 를 통 해 전체 Nginx 의 소스 코드 를 읽 는 데 도움 을 줄 수 있 습 니 다.
이 장 은 주로 Nginx 의 주요 절 차 를 분석 하기 시작 했다.
Nginx 의 메 인 프로 세 스 구현 함 수 는... / src / core / nginx. c 파일 에 있 습 니 다.main () 함 수 를 통 해 우 리 는 Nginx 가 시작 하 는 모든 절 차 를 엿 볼 수 있 습 니 다.
Nginx 시작 과정
main () 함수 의 시작 과정 은 다음 과 같 습 니 다.
  • ngx 호출get_options 방법 은 명령 행 의 인 자 를 분석 하 는 데 사 용 됩 니 다. 예 를 들 어. / nginx - s stop | start | restart
  • ngx 호출time_init 방법, 전역 변수 ngx 와 같은 시간 을 초기 화하 고 업데이트 합 니 다.cached_time
  • ngx 호출getpid 방법, 현재 프로 세 스 의 pid 를 가 져 옵 니 다.일반적으로 pid 는 / usr / local / nginx - 1.4.7 / nginx. pid 파일 에 놓 여 재 부팅, 닫 기 등 신호 명령 을 보 내 는 데 사 용 됩 니 다.
  • ngx 호출log_init 방법, 로 그 를 초기 화하 고 로 그 를 받 은 파일 핸들 ngxlog_file.fd
  • init 초기 화cycle Nginx 의 전역 변수 입 니 다.메모리 탱크 에 기본 크기 1024 의 전역 변 수 를 만 듭 니 다.이것 은 단지 가장 간단 한 초기 화 변수 일 뿐이다.
  • ngx 호출save_argv 방법, Nginx 명령 행 의 인자 와 변 수 를 저장 하고 전역 변수 ngxargv
  • ngx 호출process_options 방법, ngxget_options 에서 이 매개 변 수 를 획득 하여 ngx 에 값 을 부여 합 니 다.cycle 중.prefix, conf_prefix, conf_file, conf_param 등 필드.
  • ngx 호출os_init () 메모리 페이지 크기 ngx 와 같은 시스템 관련 변 수 를 초기 화 합 니 다.pagesize,ngx_cacheline_size, 최대 연결 수 ngxmax_sockets 등
  • ngx 호출crc32_table_init 방법, 일치 성 hash 표 초기 화, 주요 역할 은 조회 가속 화
  • ngx 호출add_inherited_sockets 방법, ngxadd_inherited_sockets 는 주로 socket 의 소켓 을 계승 했다.주요 역할 은 열 이 작 동 할 때 부 드 러 운 과도 가 필요 하 다 는 것 이다
  • .
  • ngx 호출preinit_modules 방법 은 주로 선행 초기 화 모듈 로 모듈 에 대해 번호 처리
  • 를 합 니 다.
  • ngx 호출init_cycle 방법, 전역 변수 cycle 초기 화 완료
  • ngx 호출signal_process 방법, 신호 가 있 으 면 ngx 에 들 어 갑 니 다.signal_process 방법.예 를 들 어. / nginx - s stop 은 Nginx 의 정지 신호
  • 를 처리 합 니 다.
  • ngx 호출get_conf 방법, 핵심 모듈 ngx 획득core_conf_t 의 프로필 포인터
  • ngx 호출create_pidfile 방법, pid 파일 을 만 듭 니 다.예 를 들 어 / usr / local / nginx - 1.4.7 / nginx. pid
  • ngx 호출master_process_cycle 방법, 이 함수 에서 여러 개의 Nginx 하위 프로 세 스 를 만 들 기 시작 합 니 다.이 방법 은 하위 프로 세 스 생 성, 이벤트 감청, 각종 모듈 실행 등 을 포함 합 니 다
  • 중요 절차 분석
    ngx_get_options 외부 매개 변수 분석
    ngx_get_options 방법 은 주로 명령 행 외부 인 자 를 분석 하 는 데 사 용 됩 니 다.예 를 들 어:. / nginx - s stop | start | restart
        /*        */
        if (ngx_get_options(argc, argv) != NGX_OK) {
            return 1;
        }
    /**
     *            
     * ./nginx -s stop|start|restart
     */
    static ngx_int_t
    ngx_get_options(int argc, char *const *argv)
    {
        u_char     *p;
        ngx_int_t   i;
    
        for (i = 1; i < argc; i++) {
    
            p = (u_char *) argv[i];
    
            if (*p++ != '-') {
                ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
                return NGX_ERROR;
            }
    
            while (*p) {
    
                switch (*p++) {
    
                case '?':
                case 'h':
                    ngx_show_version = 1;
                    ngx_show_help = 1;
                    break;
    
                case 'v':
                    ngx_show_version = 1;
                    break;
    
                case 'V':
                    ngx_show_version = 1;
                    ngx_show_configure = 1;
                    break;
    
                case 't':
                    ngx_test_config = 1;
                    break;
    
                case 'T':
                    ngx_test_config = 1;
                    ngx_dump_config = 1;
                    break;
    
                case 'q':
                    ngx_quiet_mode = 1;
                    break;
    
                case 'p':
                    if (*p) {
                        ngx_prefix = p;
                        goto next;
                    }
    
                    if (argv[++i]) {
                        ngx_prefix = (u_char *) argv[i];
                        goto next;
                    }
    
                    ngx_log_stderr(0, "option \"-p\" requires directory name");
                    return NGX_ERROR;
    
                case 'c':
                    if (*p) {
                        ngx_conf_file = p;
                        goto next;
                    }
    
                    if (argv[++i]) {
                        ngx_conf_file = (u_char *) argv[i];
                        goto next;
                    }
    
                    ngx_log_stderr(0, "option \"-c\" requires file name");
                    return NGX_ERROR;
    
                case 'g':
                    if (*p) {
                        ngx_conf_params = p;
                        goto next;
                    }
    
                    if (argv[++i]) {
                        ngx_conf_params = (u_char *) argv[i];
                        goto next;
                    }
    
                    ngx_log_stderr(0, "option \"-g\" requires parameter");
                    return NGX_ERROR;
    
                case 's':
                    if (*p) {
                        ngx_signal = (char *) p;
    
                    } else if (argv[++i]) {
                        ngx_signal = argv[i];
    
                    } else {
                        ngx_log_stderr(0, "option \"-s\" requires parameter");
                        return NGX_ERROR;
                    }
    
                    if (ngx_strcmp(ngx_signal, "stop") == 0
                        || ngx_strcmp(ngx_signal, "quit") == 0
                        || ngx_strcmp(ngx_signal, "reopen") == 0
                        || ngx_strcmp(ngx_signal, "reload") == 0)
                    {
                        ngx_process = NGX_PROCESS_SIGNALLER;
                        goto next;
                    }
    
                    ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
                    return NGX_ERROR;
    
                default:
                    ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
                    return NGX_ERROR;
                }
            }
    
        next:
    
            continue;
        }
    
        return NGX_OK;
    }

    init_cycle 전역 변수 초기 화
    init 초기 화cycle Nginx 의 전역 변수 입 니 다.메모리 탱크 에 기본 크기 1024 의 전역 변 수 를 만 듭 니 다.이것 은 단지 가장 간단 한 초기 화 변수 일 뿐이다.
        /*
         * init_cycle->log is required for signal handlers and
         * ngx_process_options()
         */
        /*    Nginx init_cycle */
        ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
        init_cycle.log = log;
        ngx_cycle = &init_cycle;
    
        /*           1024*/
        init_cycle.pool = ngx_create_pool(1024, log);
        if (init_cycle.pool == NULL) {
            return 1;
        }

    초기 화
    ngx_init_cycle 함수 중.ngx_init_cycle 은 Nginx 의 전역 변 수 를 모두 초기 화 하 는 과정 을 포함 하고 있 으 며, 다음 에 따로 글 을 열 어 설명 합 니 다.
        /*   cycle       */
        cycle = ngx_init_cycle(&init_cycle);
        if (cycle == NULL) {
            if (ngx_test_config) {
                ngx_log_stderr(0, "configuration file %s test failed",
                               init_cycle.conf_file.data);
            }
    
            return 1;
        }

    변수 저장 방법 ngxsave_argv 와 ngxprocess_options
    ngx_save_argv: Nginx 명령 행 의 인자 와 변 수 를 저장 하고 전역 변수 ngxargv
    ngx_process_options: ngxget_options 에서 이 매개 변 수 를 획득 하여 ngx 에 값 을 부여 합 니 다.cycle 중.prefix, conf_prefix, conf_file, conf_param 등 필드.
        /*   Nginx          ,      ngx_argv */
        if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
            return 1;
        }
    
        /*  ngx_get_options            ngx_cycle  */
        if (ngx_process_options(&init_cycle) != NGX_OK) {
            return 1;
        }
    머리의 전역 변수 정의
    /**
     *         
     */
    static ngx_uint_t   ngx_show_help; //        
    static ngx_uint_t   ngx_show_version; //       
    static ngx_uint_t   ngx_show_configure; //        
    static u_char      *ngx_prefix; //Nginx     
    static u_char      *ngx_conf_file; //          
    static u_char      *ngx_conf_params; //    
    static char        *ngx_signal; //  
    int              ngx_argc; //       
    char           **ngx_argv; //     
    char           **ngx_os_argv;
    /**
     *   Nginx          
     *       ngx_argv
     */
    static ngx_int_t
    ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
    {
    #if (NGX_FREEBSD)
    
        ngx_os_argv = (char **) argv;
        ngx_argc = argc;
        ngx_argv = (char **) argv;
    
    #else
        size_t     len;
        ngx_int_t  i;
    
        ngx_os_argv = (char **) argv;
        ngx_argc = argc;
    
        ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
        if (ngx_argv == NULL) {
            return NGX_ERROR;
        }
    
        for (i = 0; i < argc; i++) {
            len = ngx_strlen(argv[i]) + 1;
    
            ngx_argv[i] = ngx_alloc(len, cycle->log);
            if (ngx_argv[i] == NULL) {
                return NGX_ERROR;
            }
    
            (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
        }
    
        ngx_argv[i] = NULL;
    
    #endif
    
        ngx_os_environ = environ;
    
        return NGX_OK;
    }
    /**
     *  ngx_get_options            ngx_cycle 
     */
    static ngx_int_t
    ngx_process_options(ngx_cycle_t *cycle)
    {
        u_char  *p;
        size_t   len;
    
        /* Nginx     */
        if (ngx_prefix) {
            len = ngx_strlen(ngx_prefix);
            p = ngx_prefix;
    
            if (len && !ngx_path_separator(p[len - 1])) {
                p = ngx_pnalloc(cycle->pool, len + 1);
                if (p == NULL) {
                    return NGX_ERROR;
                }
    
                ngx_memcpy(p, ngx_prefix, len);
                p[len++] = '/';
            }
    
            cycle->conf_prefix.len = len;
            cycle->conf_prefix.data = p;
            cycle->prefix.len = len;
            cycle->prefix.data = p;
    
        } else {
    
    #ifndef NGX_PREFIX
    
            p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
            if (p == NULL) {
                return NGX_ERROR;
            }
    
            if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
                ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
                return NGX_ERROR;
            }
    
            len = ngx_strlen(p);
    
            p[len++] = '/';
    
            cycle->conf_prefix.len = len;
            cycle->conf_prefix.data = p;
            cycle->prefix.len = len;
            cycle->prefix.data = p;
    
    #else
    
    #ifdef NGX_CONF_PREFIX
            ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
    #else
            ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
    #endif
            ngx_str_set(&cycle->prefix, NGX_PREFIX);
    
    #endif
        }
    
        /*        */
        if (ngx_conf_file) {
            cycle->conf_file.len = ngx_strlen(ngx_conf_file);
            cycle->conf_file.data = ngx_conf_file;
    
        } else {
            ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
        }
    
        if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
            return NGX_ERROR;
        }
    
        for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
             p > cycle->conf_file.data;
             p--)
        {
            if (ngx_path_separator(*p)) {
                cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
                cycle->conf_prefix.data = ngx_cycle->conf_file.data;
                break;
            }
        }
    
        /*      */
        if (ngx_conf_params) {
            cycle->conf_param.len = ngx_strlen(ngx_conf_params);
            cycle->conf_param.data = ngx_conf_params;
        }
    
        if (ngx_test_config) {
            cycle->log->log_level = NGX_LOG_INFO;
        }
    
        return NGX_OK;
    }

    모듈 에 표시 ngxpreinit_modules
    ngx_preinit_modules 방법 은 주로 모든 모듈 을 초기 화 합 니 다.모든 모듈 에 번호 처리 하기;
        /*        ;            ;
         * ngx_modules              ,  objs/ngx_modules.c      */
        if (ngx_preinit_modules() != NGX_OK) {
            return 1;
        }

    ngx_module.c
    /**
     *        ;            ;
     */
    ngx_int_t
    ngx_preinit_modules(void)
    {
        ngx_uint_t  i;
    
        for (i = 0; ngx_modules[i]; i++) {
            ngx_modules[i]->index = i;
            ngx_modules[i]->name = ngx_module_names[i];
        }
    
        ngx_modules_n = i;
        ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES;
    
        return NGX_OK;
    }

    PID 파일 생 성 ngxcreate_pidfile
    ngx_create_pidfile PID 파일 생 성
        /*   PID   */
        if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
            return 1;
        }
    ngx_cycle.c
    /**
     *   PID   
     */
    ngx_int_t
    ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
    {
        size_t      len;
        ngx_uint_t  create;
        ngx_file_t  file;
        u_char      pid[NGX_INT64_LEN + 2];
    
        if (ngx_process > NGX_PROCESS_MASTER) {
            return NGX_OK;
        }
    
        ngx_memzero(&file, sizeof(ngx_file_t));
    
        file.name = *name;
        file.log = log;
    
        create = ngx_test_config ? NGX_FILE_CREATE_OR_OPEN : NGX_FILE_TRUNCATE;
    
        file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR,
                                create, NGX_FILE_DEFAULT_ACCESS);
    
        if (file.fd == NGX_INVALID_FILE) {
            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                          ngx_open_file_n " \"%s\" failed", file.name.data);
            return NGX_ERROR;
        }
    
        if (!ngx_test_config) {
            len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;
    
            if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
                return NGX_ERROR;
            }
        }
    
        if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                          ngx_close_file_n " \"%s\" failed", file.name.data);
        }
    
        return NGX_OK;
    }

    기타 중요 모듈
    아래 모듈 에 서 는 새로운 글 을 작성 하여 구체 적 으로 상세 하 게 해석 합 니 다.
    ngx_add_inherited_sockets 계승 Socket 파일 핸들
    ngx_init_cycle 전역 프로필 cycle 상세 설명
    ngx_signal_process 신호 처리 메커니즘
    ngx_master_process_cycle 다 중 프로 세 스 순환 메커니즘

    좋은 웹페이지 즐겨찾기