流程(从main函数开始):
-- 对参数选项进行处理
-- 初始化时间和日志等
-- 给init_cycle创建内存池
-- ngx_save_argv将命令行参数保存在全局变量中,算是备份存储,方便master进程做热代码替换之用
-- ngx_os_init完成操作系统的一些信息获取,如内存页面大小、系统限制资源等信息;将所有的这些资源都保存在对应的全局变量中。
-- ngx_crc32_table_init初始化一个做循环冗余校验的表,后续的循环冗余校验将采用高效的查表法
-- ngx_add_inherited_sockets通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1。
-- module的数量并设置每个module的index
-- ngx_init_cycle(启动时,初始化cycle结构体)
>> 对时区与时间进行一次更新操作
>> 分配一个大小为NGX_CYCLE_POOL_SIZE的内存池
>> 在内存池上分配一个ngx_cycle_t对象
>> 初始化一个链表,nginx使用链表来维护需要打开的文件以及共享内存,每个打开的文件都会放到cycle中的open_files链表中,每个共享内存段都会放到shared_memory链表中。
>> 初始化listening数组,这个数组将用于存储监听套接字
>> conf_ctx初始化了一段内存空间(可以看成是一个普通的数组),这段空间能够存储ngx_max_module(main函数中设置index时统计的所有模块的总数)个void *指针。
>> 调用所有核心模块(NGX_CORE_MODULE)的create_conf方法生成存放配置项的结构体,然后这个配置结构存储空间的地址保存到conf_ctx数组的对应单元处,寻找正确的对应单元就是通过每个模块的index字段
>> 调用ngx_conf_parse, 读取配置文件进行解析,并进行相关的设置(包括设置监听端口的处理方法),解析配置文件的时候,将会完成每个指令的set回调,这个set回调函数一般都是讲配置数据填写到配置结构中。
>> 调用所有NGX_CORE_MODULE类型模块的init_conf回调函数,完成配置结构的初始化工作。
>> 循环遍历cycle的open_files链表,如果存储了文件名就打开对应的文件。填写文件名数据就是在解析配置文件的时候完成的。除此之外很多数据的初始化都是在解析配置文件的时候完成。执行了打开文件操作之后,open_files链表就不光保存了文件名了,还保存了文件描述符等信息。
>> 循环遍历cycle的shared_memory,初始化各个共享内存段
>> 遍历listening数组,打开所有的监听套接口,同时设置一些socket选项以及文件描述符属性,如非阻塞等。
>> 调用所有模块的init_module(目前只有ngx_event_core_module设置了该回调函数)
++ 首先取得ngx_events_module在conf_ctx中存储的配置结构体数组的地址
++ 取得ngx_event_core_module模块的配置结构
++ 取得ngx_core_module模块的配置结构
++ 从ngx_core_module模块的配置结构中获取timer_resoluting指令的配置参数
++ 创建共享内存实现锁等工作
++
-- ngx_init_signals注册一堆信号处理程序
-- 如果需要daemon,调用ngx_daemon实现守护进程
-- 完成了初始化工作,调用ngx_signal_process_cycle或ngx_master_process_cycle
>> 调用所有模块的init process方法(目前只看到ngx_event_core_module模块设置了这个方法)
-- ngx_event_core_module中的ngx_event_process_init方法
>> 获取相应模块的配置结构(ngx_core_module与ngx_event_core_module)
>> ngx_event_timer_init,初始化计时器,此处将会创建一颗红黑树,来维护计时器
>> 遍历模块数组(非NGX_EVENT_MODULE和非use配置指令指定的模块都会跳过),调用具体时间模块的init函数
>> 针对use设置的event模块调用actions.init方法(对于epoll,调用的是ngx_epoll_init方法)
++ epoll模块中的ngx_epoll_init方法会将全局变量ngx_events_actions设置为epoll模块中的actions
>> 创建一个connections数组,维护所有的connections,本过程已经狮子啊worker进程中了,所以是每个worker都有自己的connection数组
>> 分配connection_n个空间给read_events和write_events,并进行初始化
>> 把connection和read_event、write_event联系起来,每个connection都指向一个read_event和write_event
>> 循环设置listening sockets(包括设置对应connection的read为ngx_event_accept
++ 获取一个空闲的connection,并设置其fd为listening fd
++ 设置connection->read的handler为ngx_event_accept(该函数会调用ngx_listening_t的handler,对于http框架会调用ngx_http_init_connection)
++ 将listening fd加入epoll监听,其中事件中的data的ptr设置为对应的connection,以便回调。
++ listening fd的回调是调用ngx_event_accept
~~ accept
~~ 获取新的connection
~~ 设置connection的回调函数
~~ 调用ngx_listening_t的handler(ngx_http_init_connection)
>> 进入死循环,处理事件
-- ngx_process_events_and_timers
-- 调用ngx_process_events(实际上就是ngx_events_actions的process_events函数,如果是epoll,那么调用的就是ngx_epoll_process_events函数)