nginx main的初始化过程

本文详细剖析了Nginx 1.18.0版本的启动流程,从main函数开始,包括ngx_debug_init()的调试初始化、ngx_strerror_init()的错误信息处理、ngx_get_options()的命令行参数解析、ngx_ssl_init()的SSL模块初始化、ngx_init_cycle()的周期初始化等关键步骤。此外,还涉及了内存池、信号处理、配置文件解析等核心功能的实现。
摘要由CSDN通过智能技术生成

下载的代码版本是nginx-1.18.0

  • 从nginx-1.18.0/src/core/nginx.c的main函数调用次序开始

ngx_debug_init

    ngx_debug_init();

    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

ngx_debug_init是初始化debug用的,nginx中的debug,主要是对内存池分配管理方面的debug,因为作为一个应用程序,最容易出现bug的地方也是内存管理这块。在Linux版本中,这个函数只是一个空定义src/os/unix/ngx_linux_config.h,还有两个版本,src/os/unix/ngx_darwin_init.csrc/os/unix/ngx_freebsd_init.c中有定义。

ngx_strerror_init把error值从0到135转成字符串,保存在nginx的ngx_sys_errlist中,供后续使用。

ngx_get_options处理命令行参数,如果是-h选项,打印help输出。

ngx_show_version_info

    if (ngx_show_version) {
        ngx_show_version_info();

        if (!ngx_test_config) {
            return 0;
        }
    }

输出版本信息,help信息也是在ngx_show_version_info里面通过ngx_show_help变量输出的。

ngx_time_init

初始化nginx的时间相关变量

volatile ngx_msec_t      ngx_current_msec;
volatile ngx_time_t     *ngx_cached_time;
volatile ngx_str_t       ngx_cached_err_log_time;
volatile ngx_str_t       ngx_cached_http_time;
volatile ngx_str_t       ngx_cached_http_log_time;
volatile ngx_str_t       ngx_cached_http_log_iso8601;
volatile ngx_str_t       ngx_cached_syslog_time;

ngx_regex_init

如果定义了NGX_PCRE,ngx_regex_init会对正则表达式库PCRE进行初始化。

PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。

\#if (NGX_PCRE)ngx_regex_init();

\#endif

ngx_log_init

初始化ngx_pid和ngx_parent
初始化nginx log子系统

    ngx_pid = ngx_getpid();
    ngx_parent = ngx_getppid();

    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

log文件记录在NGX_PREFIX/logs/error.log文件中

这些文件在configure执行后自动生成ngx_auto_config.h

ngx_auto_config.h:#define NGX_PREFIX  "/usr/local/nginx/"
ngx_auto_config.h:#define NGX_CONF_PREFIX  "conf/"
ngx_auto_config.h:#define NGX_SBIN_PATH  "sbin/nginx"
ngx_auto_config.h:#define NGX_CONF_PATH  "conf/nginx.conf"
ngx_auto_config.h:#define NGX_PID_PATH  "logs/nginx.pid"
ngx_auto_config.h:#define NGX_LOCK_PATH  "logs/nginx.lock"
ngx_auto_config.h:#define NGX_ERROR_LOG_PATH  "logs/error.log"
ngx_auto_config.h:#define NGX_HTTP_LOG_PATH  "logs/access.log"

ngx_ssl_init

#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

在ngx_ssl_init中有openssl版本号做分支的代码,版本号大于等于0x10100003L的走的是OPENSSL_init_ssl的接口,小于这个走的是OPENSSL_config,SSL_library_init接口,后面需要再具体深入看一下。

ngx_memzero & ngx_create_pool

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;

    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }

全局变量init_cycle清零,并创建改变量的内存池pool,这个需要再结合cycle_init深入看一下。

ngx_save_argv

    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

保存命令行参数至全局变量ngx_os_argv、ngx_argc、ngx_argv

ngx_process_options

初始化全局变量init_cycle中的成员:prefix、conf_prefix、conf_file、conf_param 等字段

ngx_os_init

初始化系统相关变量,如:内存页面大小ngx_pagesize、最大连接数ngx_max_sockets等,这里面sysconf,sysinfo的系统调用用的比较多。比如获取系统pagesize,cpu核数等就是通过sysconf获取的。

ngx_crc32_table_init

初始化 CRC 表(循环冗余校验表)

ngx_add_inherited_sockets

通过环境变量NGINX完成socket的继承,将其保存在全局变量init_cycle的listening数组中。

ngx_preinit_modules

初始化每个模块module的index,并计算ngx_max_module

ngx_modules定义了所有的nginx module,在configure阶段,编译不同的参数就需要通过configure参数指定不同的module。

ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    &ngx_rtmp_module,
    &ngx_rtmp_core_module,
    &ngx_rtmp_cmd_module,
    &ngx_rtmp_codec_module,
    &ngx_rtmp_access_module,
    &ngx_rtmp_record_module,
    &ngx_rtmp_live_module,
    &ngx_rtmp_play_module,
    &ngx_rtmp_flv_module,
    &ngx_rtmp_mp4_module,
    &ngx_rtmp_netcall_module,
    &ngx_rtmp_relay_module,
    &ngx_rtmp_exec_module,
    &ngx_rtmp_auto_push_module,
    &ngx_rtmp_auto_push_index_module,
    &ngx_rtmp_notify_module,
    &ngx_rtmp_log_module,
    &ngx_rtmp_limit_module,
    &ngx_rtmp_hls_module,
    &ngx_rtmp_dash_module,
    &ngx_openssl_module,
    &ngx_regex_module,
    &ngx_events_module,
    &ngx_event_core_module,
    &ngx_epoll_module,
    &ngx_http_module,
    &ngx_http_core_module,
    &ngx_http_log_module,
    &ngx_http_upstream_module,
    &ngx_http_static_module,
    &ngx_http_autoindex_module,
    &ngx_http_index_module,
    &ngx_http_mirror_module,
    &ngx_http_try_files_module,
    &ngx_http_auth_basic_module,
    &ngx_http_access_module,
    &ngx_http_limit_conn_module,
    &ngx_http_limit_req_module,
    &ngx_http_geo_module,
    &ngx_http_map_module,
    &ngx_http_split_clients_module,
    &ngx_http_referer_module,
    &ngx_http_rewrite_module,
    &ngx_http_ssl_module,
    &ngx_http_proxy_module,
    &ngx_http_fastcgi_module,
    &ngx_http_uwsgi_module,
    &ngx_http_scgi_module,
    &ngx_http_memcached_module,
    &ngx_http_empty_gif_module,
    &ngx_http_browser_module,
    &ngx_http_flv_module,
    &ngx_http_mp4_module,
    &ngx_http_upstream_hash_module,
    &ngx_http_upstream_ip_hash_module,
    &ngx_http_upstream_least_conn_module,
    &ngx_http_upstream_random_module,
    &ngx_http_upstream_keepalive_module,
    &ngx_http_upstream_zone_module,
    &ngx_rtmp_stat_module,
    &ngx_rtmp_control_module,
    &ngx_http_write_filter_module,
    &ngx_http_header_filter_module,
    &ngx_http_chunked_filter_module,
    &ngx_http_range_header_filter_module,
    &ngx_http_gzip_filter_module,
    &ngx_http_postpone_filter_module,
    &ngx_http_ssi_filter_module,
    &ngx_http_charset_filter_module,
    &ngx_http_userid_filter_module,
    &ngx_http_headers_filter_module,
    &ngx_http_copy_filter_module,
    &ngx_http_range_body_filter_module,
    &ngx_http_not_modified_filter_module,
    NULL
};

ngx_init_cycle

初始化全局变量init_cycle,这个是最重要的部分,需要分解来看。

  • 更新时区与时间
  • 创建内存池
  • 分配 ngx_cycle_t 结构体内存,创建该结构的变量 cycle 并初始化
  • 遍历所有 core模块,并调用该模块的 create_conf() 函数
  • 配置文件解析
  • 遍历所有core模块,并调用core模块的init_conf()函数
  • 遍历 open_files 链表中的每一个文件并打开
  • 创建新的共享内存并初始化
  • 遍历 listening 数组并打开所有侦听
  • 提交新的 cycle 配置,并调用所有模块的init_module
  • 关闭或删除不被使用的在 old_cycle 中的资源
  • 释放多余的共享内存
  • 关闭多余的侦听 sockets
  • 关闭多余的打开文件

ngx_signal_process

ngx_signal_process 函数从配置文件中获取 nginx 进程 pid 文件路径,然后读取文件里的 pid ,最后调用 ngx_os_signal_process 函数,ngx_os_signal_process 函数是与操作系统相关的函数,它将 ngx_signal 的值与全局数组 signals 中各项比较,如果名字相同,就调用 kill 向正在运行的 nginx master 进程发送特定的信号。

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 }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值