IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

Nginx启动初始化过程(一)

淘宝数据平台团队 2010-12-02 22:32:15 累计浏览 5,462 次
本机暂存

Nginx的启动初始化在src/core/nginx.c的main函数中完成,当然main函数是整个Nginx的入口,除了完成启动初始化任务以外,也必定是所有功能模块的入口之处。Nginx的初始化工作主要围绕一个类型为ngx_cycle_t类型的全局变量(cycle)展开。下面具体看一下main函数为Nginx的启动过程做了哪些初始化方面的事情。(以下代码段都是顺序从main函数中摘取出来的, 对照源码阅读可能更易明白)

main函数做的第一件事情就是对参数选项进行处理,和普通的Linux程序如出一辙,如下:

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

Nginx用此函数对参数选项进行解析,从而采取相应的动作,比如:显示版本、测试配置等功能。其实此函数实现的很简陋,远没有Linux提供的getopt()那么强悍,但却可以达到跨平台的目的。

     ngx_time_init();
#if (NGX_PCRE)
    ngx_regex_init();
#endif
    ngx_pid = ngx_getpid();
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

上述几行代码的功能如其名,主要完成Nginx在时间和日志等方面的初始化工作。

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

将命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。这算是一个备份存储,方便以后master进程做热代码替换之用。

     if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }


完成操作系统的一些信息获取,如内存页面大小、系统限制资源等信息;所有的这些资源都将会被保存在对应的全局变量中,因此后续访问将会很便利。

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

初始化一个做循环冗余校验的表,由此可以看出后续的循环冗余校验将采用高效的查表法。crc算法此处就不做分析,网上一堆一堆的相关资料,有兴趣的同学可以了解。

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

通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1。

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

额!!!这个循环中的ngx_modules数组好像没见定义,难不成是火星来的?当然不是,如其名,这就是一个存储所有模块的信息,包括自己开发的模块都会放到这个数组中,而这个神秘的数组却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中。这个循环的目的是清晰可见的――对所有模块进行索引编号,方便以后访问;同时借助ngx_max_module对所有模块进行了一次点数,确定究竟有多少模块。而神秘数组ngx_modules的长相大概如下:

ngx_module_t *ngx_modules[] = {
    &ngx_core_module,
    &ngx_errlog_module,
    &ngx_conf_module,
    &ngx_events_module,
    &ngx_event_core_module,
    &ngx_epoll_module,
    &ngx_openssl_module,
    &ngx_http_module,
    。。。
};
    cycle = ngx_init_cycle(&init_cycle);

这里将会初始化很多的东东到全局变量cycle中,是Nginx启动初始化的核心之处。ngx_init_cycle函数的过程比较多,放下一篇blog中逐段分析。

    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

注册一堆信号处理程序,需要注册的信号及相应的信号处理函数被放在一个类型为ngx_signal_t的数组signals中。数组定义在src/os/unix/ngx_process.c中。ngx_signal_t结构类型定义了信号值,信号名字,信号对应动作名以及信号处理函数。

     if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }
        ngx_daemonized = 1;
    }

ngx_daemon肯定就是用来实现守护进程的函数了,此处就不多废话了,有需要写server程序的,可以直接copy这段代码实现守护进程。

    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

玩过Nginx的人都知道,Nginx启动后有一个记录进程id的文件,这个文件里面就一个pid。原来这个pid就是在这个地方记录下来的。查看ngx_create_pidfile函数可以看到这样的一行代码

if (ngx_process > NGX_PROCESS_MASTER) {
return NGX_OK;
},这行代码就说明了,不是master进程时,就不创建这样的一个pid文件。

    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle(cycle);
    } else {
        ngx_master_process_cycle(cycle);
    }

到此就基本完成Nginx的启动初始化过程了,即将开始进程相关的工作了,这里最重要的ngx_master_process_cycle这个过程,在这个过程里实现了master-worker模式的进程模型,也是生成环境下Nginx的常用模型。既然此处已不再是初始化工作,那么就留到后续分析吧。

上述所有过程都是在main函数里完成的,下一篇分析ngx_init_cycle函数。

同分类推荐文章

  1. Vibe新开源项目 - Vaala AI Gateway (2026-05-17 02:10:19)
  2. SmartPerfetto 架构文章 Q&A:8 个深度技术问答 (2026-04-10 11:00:00)
  3. 让 AI 把我的 PHP 博客重写成 Go (2026-03-27 18:33:54)

查看更多 后端 文章 →

建议继续学习

  1. 配置Nginx+uwsgi更方便地部署python应用 (累计阅读 106,963)
  2. 搜狐闪电邮箱的 Nginx/Postfix 使用模式 (累计阅读 33,821)
  3. 记录一个软中断问题 (累计阅读 16,885)
  4. 解析nginx负载均衡 (累计阅读 16,503)
  5. server日志的路径分析 (累计阅读 11,181)
  6. Nginx模块开发入门 (累计阅读 11,101)
  7. 检查nginx配置,重载配置以及重启的方法 (累计阅读 10,782)
  8. Cacti 添加 Nginx 监控 (累计阅读 10,521)
  9. 使用Squid缓存视频 (累计阅读 10,280)
  10. fsockopen 异步处理 (累计阅读 10,280)