【读nginx】

发布时间:2024年01月12日
1) 初始化错误提示列表,以errno为下标,元素就是对应的错误提示信息。

   1: if (ngx_strerror_init() != NGX_OK) {
   2:     return 1;
   3: }
2)获取命令行参数,保存在全局变量中,可以设置的命令行参数如下表所示:

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

3)时间、正则表达式和log的初始化。

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

  4)初始化cycle结构,并创建内存块大小为1024的内存池,内存池创讨论过了,nginx框架就是围绕着ngx_cycle_t结构体来控制运行的
   1: ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
   2: init_cycle.log = log;
   3: ngx_cycle = &init_cycle;
   4:  
   5: init_cycle.pool = ngx_create_pool(1024, log);
   6: if (init_cycle.pool == NULL) {
   7:     return 1;
   8: }

5)  将命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。这算是一个备份存储,方便以后master进程做热代码替换之用。
   1: if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
   2:         return 1;
   3: }

6)用命令行参数得来的全局变量初始化cycle的conf_prefix(配置文件所在路径的前缀)、prefix(nginx可执行文件所在路径)、conf_file(配置文件名)和conf_param(通过命令行-g选项指定的全局配置信息)。
   1: if (ngx_process_options(&init_cycle) != NGX_OK) {
   2:     return 1;
   3: }


7)  根据操作系统确定一些参数,信息会被保存到一些全局变量中,如页大小ngx_pagesize, CPU cacheline
   1: if (ngx_os_init(log) != NGX_OK) {
   2:     return 1;
   3: }

8) 初始化一个做循环冗余校验的表,由此可以看出后续的循环冗余校验将采用高效的查表法
   1: if (ngx_crc32_table_init() != NGX_OK) {  
   2:        return 1;  
   3:    } 

9)通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。同时可以读取master进程传递的平滑升级信息等等
   1: if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {  
   2:         return 1;  
   3:     }  

10)初始化所有模块的index信息,即对所有模块进行编号,ngx_modules数却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中

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

11)  用上面收集的init_cycle信息初始化ngx_cycle,这行代码是nginx启动过程中最重要的一个步骤,在第3节将详细展开。

   1: cycle = ngx_init_cycle(&init_cycle);
   2: if (cycle == NULL) {
   3:     if (ngx_test_config) {
   4:         ngx_log_stderr(0, "configuration file %s test failed",
   5:                        init_cycle.conf_file.data);
   6:     }
   7:  
   8:     return 1;
   9: }
 

12)ccf 为ngx_core_conf_t 将在第2节给出详细定义,这个地方需要解释下,ccf->master是从配置文件中解析master_process配置项所得的值,初始化为NGX_CONF_UNSET(-1),在配置项中,如果flag类型的配置项master_process被设置为on,则其值为1,如果为off,则其值为0,ngx_process为全局变量,用于记录要采用的工作模式,未被初始化,因此初始值是0(uint型全局变量会被系统默认初始化为0),相关宏定义如下:

#define NGX_PROCESS_SINGLE     0
#define NGX_PROCESS_MASTER     1
#define NGX_PROCESS_SIGNALLER  2
#define NGX_PROCESS_WORKER     3
#define NGX_PROCESS_HELPER     4
因此,下面的if判断语句的含义就是:用来处理一种特殊情况,即如果在配置项中未设置master_process配置项或者是设置为打开,ngx_process未被设置,采用默认值0,这个时候要采用master工作模式。因为master_process优先级高,且nginx默认采用master模式如果在配置项中设置master_process为off,那么if依据不会执行。最终nginx工作模式取决于ngx_proces的初值0,即采用单进程模式。

 

   1: ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
   2:  
   3: if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
   4:     ngx_process = NGX_PROCESS_MASTER;
   5: }
13)初始化信号;主要完成信号处理程序的注册

   1: if (ngx_init_signals(cycle->log) != NGX_OK) {
   2:     return 1;
   3: }
14)若无继承sockets,且设置了守护进程表示,则创建守护进程

   1: if (!ngx_inherited && ccf->daemon) {  
   2:         if (ngx_daemon(cycle->log) != NGX_OK) {  
   3:             return 1;  
   4:         }  
   5:   
   6:         ngx_daemonized = 1;  
   7:     }  
   8:   
   9:     if (ngx_inherited) {  
  10:         ngx_daemonized = 1;  
  11: }  
15) 创建进程记录文件;(非NGX_PROCESS_MASTER=1进程,不创建该文件)

   1: if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
   2:     return 1;
   3: }
16)  进入进程主循环,根据ngx_process确定启动单进程模式还是多进程模式。

   1: if (ngx_process == NGX_PROCESS_SINGLE) {
   2:      ngx_single_process_cycle(cycle);
   3:  
   4:  } else {
   5:      ngx_master_process_cycle(cycle);
   6:  }
2.相关结构体
2.1. ngx_module_t
nginx中所有模块的类型都是ngx_module_t类型的,定义了模块的一些属性。nginx是完全模块化的,所有的组件都是模块,从而实现了nginx的高度松耦合。同时,我们在进行nginx模块开发时,也离不开这个数据结构。在上面初始化过程中的第10步就是初始化这个结构。

   1: struct ngx_module_s {
   2:     /**
   3:      * 在具体类型模块(http、event等)的全局配置结构数组的下标。以http module模块为例,
   4:      * nginx把所有的http module的config信息存放在ngx_http_conf_ctx_t类型的变量中,
   5:      * 这个变量只有3个属性,分别是所有http module的main、srv、loc的config信息的数组。
   6:      * 如果该模块是http module,则ctx_index是该模块的config信息(main、srv、loc)
   7:      * 在ngx_http_conf_ctx_t中的下标。
   8:      */
   9:     ngx_uint_t            ctx_index;
  10:  
  11:     /**
  12:      * nginx把所有模块(ngx_module_t)存放到ngx_modules数组中,这个数组在nginx源码路
  13:      * 径的objs/ngx_modules.c中,是在运行configure脚本后生成的。index属性就是该模块
  14:      * 在ngx_modules数组中的下标。同时nginx把所有的core module的配置结构存放到ngx_cycle的
  15:      * conf_ctx数组中,index也是该模块的配置结构在ngx_cycle->conf_ctx数组中的下标。
  16:      */
  17:     ngx_uint_t            index;
  18:  
  19:     ……
  20:  
  21:     /**
  22:      * 模块的上下文属性,同一类型的模块的属性是相同的,比如core module的ctx是ngx_core_module_t类型。
  23:      * 而http module的ctx是ngx_http_moduel_t类型,event module的ctx是ngx_event_module_t类型等等。
  24:      * 相应类型的模块由分开处理的,比如所有的http module由ngx_http_module解析处理,而所有的event module
  25:      * 由ngx_events_module解析处理。
  26:      */
  27:     void                 *ctx;
  28:  
  29:     /**
  30:      * 该模块支持的指令的数组,最后以一个空指令结尾。ngx_commond_t的分析见下文。
  31:      */
  32:     ngx_command_t        *commands;
  33:  
  34:     /**
  35:      * 模块的类型,nginx所有的模块类型:
  36:      *         NGX_CORE_MODULE
  37:      *         NGX_CONF_MODULE
  38:      *         NGX_HTTP_MODULE
  39:      *         NGX_EVENT_MODULE
  40:      *         NGX_MAIL_MODULE
  41:      * 这些不同的类型也指定了不同的ctx。
  42:      */
  43:     ngx_uint_t            type;
  44:  
  45:     /* 接下来都是一些回调函数,在nginx初始化过程的特定时间点调用 */
  46:     ngx_int_t           (*init_master)(ngx_log_t *log);
  47:  
  48:     /* 初始化完所有模块后调用,在ngx_int_cycle函数(ngx_cycle.c)中 */
  49:     ngx_int_t           (*init_module)(ngx_cycle_t *cycle);
  50:  
  51:     /* 初始化完worker进程后调用,在ngx_worker_process_init函数(ngx_process_cycle.c)中 */
  52:     ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
  53:     ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
  54:     void                (*exit_thread)(ngx_cycle_t *cycle);
  55:     void                (*exit_process)(ngx_cycle_t *cycle);
  56:  
  57:     void                (*exit_master)(ngx_cycle_t *cycle);
  58:     ……
  59: };

2) 创建内存池,并从内存池中创建ngx_cycle_t结构,然后给cycle日志和old_cycle赋值

 

   1: log = old_cycle->log;
   2:  
   3: pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log);
   4: if (pool == NULL) {
   5:     return NULL;
   6: }
   7: pool->log = log;
   8:  
   9: cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
  10: if (cycle == NULL) {
  11:     ngx_destroy_pool(pool);
  12:     return NULL;
  13: }
  14:  
  15: cycle->pool = pool;
  16: cycle->log = log;
  17: cycle->old_cycle = old_cycle;

文章来源:https://blog.csdn.net/weixin_45397344/article/details/135558977
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。