nginx的源代码结构如图:
入口程序, 及主程序位于src/core/nginx.c中的main函数, 下面来简单的过下这个主函数做了些什么事情:
- ngx_debug_init() 调试相关的初始化, 用于开发环境的调试
- ngx_strerror_init() 错误信息相关的初始化, 如果初始化失败, 则直接退出
- ngx_get_options() 获取命令行的参数选项,并将对应的参数值赋值给具体的变量, 比如ngx_show_version, ngx_show_help之类的变量, 继而后面可选择性的执行相应的处理。
- 接下来基本上是根据命令行参数,是否显示版本号, 是否显示帮助, 是否显示配置信息给用户呈现一些提示性的信息。
- ngx_max_sockets = -1; 初始化ngx_max_sockets ,该变量在os/unix/ngx_posix_init.c中定义, 为ngx_int_t类型。
- ngx_time_init() 时间初始化
- ngx_regex_init() 正则初始化, 如果启用PCRE的话会进行正则的初始化。
- ngx_pid = ngx_getpid() 获取当前进程ID
- log = ngx_log_init(ngx_prefix) 初始化日志对象, 如果初始化失败, 则直接退出。
- ngx_ssl_init() 在启用了nginx的openssl的时候, 会对ssl进行初始化
- ngx_memzero(&init_cycle, sizeof(ngx_cycle_t)) 将初始化周期对象初始化为全零状态。
- init_cycle.log = log; ngx_cycle = &init_cycle; 初始化ngx_cycle对象。该对象是在core/ngx_cycle.c中定义的volatile ngx_cycle_t *ngx_cycle;
- 分配内存池init_cycle.pool = ngx_create_pool(1024, log); 为ngx_cycle.pool对象创建1024B的内存池。内存池初始化失败就直接返回。
- ngx_save_argv(&init_cycle, argc, argv) 将命令行参数保存到ngx_os_argv、ngx_argc以及ngx_argv这几个全局的变量中。这算是一个备份存储,方便以后master进程做热代码替换之用。 如果保存失败也会直接退出。 这个过程会用到init_cycle的log对象, 对内存的分配做日志性记录之用。
- ngx_process_options(&init_cycle) : 初始化init_cycle中的一些如: conf_file,prefix,conf_prefix等字段, 失败也是直接返回。
- ngx_os_init(log) : 完成操作系统的一些信息获取,如内存页面大小、系统限制资源,ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等。 所有的这些资源都将会被保存在对应的全局变量中,因此后续访问将会很便利。同样失败会退出。
- ngx_crc32_table_init(): 初始化一个做循环冗余校验的表,由此可以看出后续的循环冗余校验将采用高效的查表法。 失败直接退出。
- ngx_add_inherited_sockets(&init_cycle) : 通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1。失败直接退出。
- 将nginx中的模块全部索引起来, 其中所有模块在编译后的ngx_modules.c中定义, 这个变量是在编译后才出现的,和编译条件密切相关, 也就是说nginx需要添加模块, 需要重新编译. ngx_max_module = 0;
1. for (i = 0; ngx_modules[i]; i++) {
ngx_modules[i]->index = ngx_max_module++;
}
- cycle = ngx_init_cycle(&init_cycle) : 对ngx_cycle结构进行初始化,这里是nginx启动核心之处, 会将很多东西放在init_cycle中.详细见ngx_cycle.c中的 ngx_init_cycle方法.初始化失败会直接退出。
- 如果有信号进来, 进入ngx_signal_process处理信号。
1. if (ngx_signal) {
return ngx_signal_process(cycle, ngx_signal);
}
- ngx_os_status(cycle->log) 操作系统状态日志记录
- 获取核心模块的配置信息:ngx_cycle = cycle;
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); - ngx_init_signals(cycle->log) : 非win32系统信号初始化。注册一堆信号处理程序,需要注册的信号及相应的信号处理函数被放在一个类型为ngx_signal_t的数组signals中。数组定义在src/os/unix/ngx_process.c中。ngx_signal_t结构类型定义了信号值,信号名字,信号对应动作名以及信号处理函数。失败退出。
- ngx_daemon(cycle->log) : ngx_daemon肯定就是用来实现守护进程的函数了, 有需要写server程序的,可以直接copy这段代码实现守护进程。代码实现位于 ./src/os/unix/ngx_daemon.c , 还是非win32系统。
- ngx_create_pidfile(&ccf->pid, cycle->log) : 创建一个pid文件, 玩过nginx的都知道, 启动的时候就会生成一个pid文件, 那个文件的产生就是这里来的。
- 最后根据使用单进程还是多进程的方式, 当然服务器都是多进程, 只有调试的时候会启用单进程, 这里分别调用ngx_single_process_cycle(cycle)来单进程处理。ngx_master_process_cycle(cycle)多进程处理, 其实这两个函数都是一个无限循环函数,实现服务的功能。
以上就是主功能的完整过程。 后续会对每个单独的步骤做详细的介绍。