Nginx的启动初始化在src/core/nginx.c的main函数中完成,当然main函数是整个Nginx的入口,除了完成启动初始化任务以外,也必定是所有功能模块的入口之处。Nginx的初始化工作主要围绕一个类型为ngx_cycle_t类型的全局变量(cycle)展开。下面具体看一下main函数为Nginx的启动过程做了哪些初始化方面的事情。


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

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

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

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


  1. ngx_time_init();
  2. (NGX_PCRE)
  3. ngx_regex_init();
  4. if
  5. ngx_pid = ngx_getpid();
  6. log = ngx_log_init(ngx_prefix);
  7. if (log == NULL) {
  8. return 1;
  9. }

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; }

上述几行代码的功能如其名,time和log后面再用单独的文字来分析,此处就不多说了。


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

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

将命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。这应该算是一个备份存储,方便后面的初始化工作能够随时获取命令行参数。


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

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

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


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

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

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


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

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

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


  1. ngx_max_module = 0;
  2. for (i = 0; ngx_modules[i]; i++) {
  3. ngx_modules[i]->index = ngx_max_module++;
  4. }

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的长相大概如下:

  1. ngx_module_t *ngx_modules[] = {
  2. &ngx_core_module,
  3. &ngx_errlog_module,
  4. &ngx_conf_module,
  5. &ngx_events_module,
  6. &ngx_event_core_module,
  7. &ngx_epoll_module,
  8. &ngx_openssl_module,
  9. &ngx_http_module,
  10. 。。。
  11. };

  1. cycle = ngx_init_cycle(&init_cycle);

cycle = ngx_init_cycle(&init_cycle);

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


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

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

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


  1. if (!ngx_inherited && ccf->daemon) {
  2. if (ngx_daemon(cycle->log) != NGX_OK) {
  3. return 1;
  4. }
  5. ngx_daemonized = 1;
  6. }

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

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


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

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文件。


  1. if (ngx_process == NGX_PROCESS_SINGLE) {
  2. ngx_single_process_cycle(cycle);
  3. } else {
  4. ngx_master_process_cycle(cycle);
  5. }

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的常用模型。既然此处已不再是初始化工作,那么就留到后续分析吧。

转载于:https://www.cnblogs.com/li-hao/archive/2013/02/28/2937258.html

Nginx源码分析-启动初始化过程(一)相关推荐

  1. Nginx源码分析:启动流程

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> nginx简介 Nginx的作为服务端软件,表现的主要特点是更快.高扩展.高可靠性.低内存消 ...

  2. nginx源码分析(5)——监听socket初始化

    在nginx源码分析(4)中,看到了nginx的事件模型,但其中没有介绍监听socket的初始化.而对于web server来说,需要通过监听socket来监听客户端的连接等.本篇将会具体介绍这方面的 ...

  3. golang源码分析-启动过程概述

    golang源码分析-启动过程概述 golang语言作为根据CSP模型实现的一种强类型的语言,本文主要就是通过简单的实例来分析一下golang语言的启动流程,为深入了解与学习做铺垫. golang代码 ...

  4. springboot集成mybatis源码分析-启动加载mybatis过程(二)

    springboot集成mybatis源码分析-启动加载mybatis过程(二) 1.springboot项目最核心的就是自动加载配置,该功能则依赖的是一个注解@SpringBootApplicati ...

  5. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

  6. Nginx源码分析:master/worker工作流程概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> Nginx的master与worker工作模式 在生成环境中的Nginx启动模式基本都是以m ...

  7. Nginx 源码分析

    1.工程 ngx_conf_file.c ngx_connection.c ngx_cycle.c ngx_file.h ngx_module.c ngx_open_file_cache.h ngx_ ...

  8. Nginx源码分析:epoll事件处理模块概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 事件处理模块概述 Nginx的高效请求的处理依赖于事件管理机制,本次默认的场景是Linux操 ...

  9. Nginx源码分析:惊群处理与负载均衡

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> Nginx的惊群处理与负载均衡概述 当Nginx工作在master/worker模式下时,就 ...

最新文章

  1. php函数serialize()与unserialize()
  2. 当OpenCV遇到VS2019时,以前的配置方式翻车了….
  3. 5G NR基础参数及帧结构
  4. linux启动后分区数据变化,求助!我删除了Linux启动分区
  5. 【结论】Number(jzoj(gz) 1781)
  6. python装饰器的顺序_python中多个装饰器的执行顺序详解
  7. MySQL优化原理分析及优化方案总结
  8. 在MVVM模式下,ListBox的Command绑定
  9. nc扫描端口-curl-手动查杀木马过程之生成木马程序病原体并自动运行
  10. 飞机大战-玩家飞机被击中
  11. 一个检查输入内容的 AppCompatEditText 。
  12. 节奏大师显示服务器,节奏大师上线首日登录困难 服务器拖累腾讯游戏
  13. BindingResult的使用
  14. anaconda的默认位置修改pkgs以及默认创建环境踩坑
  15. D3D管线以及着色器工作原理-画一个三角形
  16. Name or service not known, ping域名报错
  17. 智能驾驶是什么意思_智能驾驶当道,谁还在谈驾驶乐趣?
  18. C/C++:实现象棋游戏
  19. 使用es6把new Date()出的默认时间换成 xxx年xxx月xxx日 15:20:03
  20. Alexa关闭,最好的SEO工具轮到谁了?

热门文章

  1. convert.todatetime指定日期格式_JDK1.8新增日期时间类型
  2. android studio管理依赖,Android Studio 中的 Gradle 依赖统一管理
  3. Java h264起始码_h.264 – 使用H264视频的起始码
  4. codeforces Restore Cube(暴力枚举)
  5. 指针(*)、取地址()、解引用(*)与引用()
  6. python对象点方法_python面向对象知识点疏理
  7. kernal tch 下载 天正_tch kernal.arx
  8. vb6 打印选项对话框_图纸打印次数太多,不知道哪次才是最新的?用打印戳记区分效果好...
  9. php外部对象如何使用方法,php面向对象全攻略 (三)特殊的引用“$this”的使用...
  10. 和python哪个容易胖_为什么有些人特别容易胖?