Nginx学习笔记(十二):核心结构体
2014-02-16 17:06
344 查看
前言
继续源码。。。核心结构
Nginx核心的框架代码是一直在围绕 ngx_cycle_t这个核心结构体来控制进程运行的。无论是master管理进程,worker工作进程还是cache manager(loader)进程,它们都毫无例外地拥有唯一的一个ngx_cycle_t结构体。
ngx_cycle_t结构体
首先,Nginx的可配置性完全依赖于nginx.conf配置文件,Nginx所有模块的可定制性、可伸缩性等诸多特性也依赖于nginx.conf配置文件,因此,配置文件路径需要保存在ngx_cycle_t中;有了配置文件后,Nginx框架就需要开始根据配置项加载所有模块。......。下面,介绍下ngx_cycle_t的成员:
typedef struct ngx_cycle_s ngx_cycle_t; struct ngx_cycle_s { /* * 保存所有模块存储配置项的结构体指针 * 为什么是四重指针?之前已有笔记,详见《笔记五》中的<设定配置项解析方式> */ void ****conf_ctx; ngx_pool_t *pool; // 内存池 /* * 在没有执行ngx_init_cycle方法之前,即没有解析配置项前,如果有信息输出到日志, * 会暂时使用此成员,将log输出到屏幕。在使用ngx_init_cycle方法后,则会根据nginx.conf * 配置文件中的配置项,构造出正确的日者文件,此时对log重新赋值 */ ngx_log_t *log; /* * 由nginx.conf配置文件读取到日志文件路径后,开始初始化error_log日志文件, * 此时,因为上面log成员还在用于输出日志到屏幕,则用此成员暂时替代log成员, * 待初始化成功后,再用new_log成员的地址覆盖log指针 */ ngx_log_t new_log; ngx_uint_t log_use_stderr; /* unsigned log_use_stderr:1; */ /* 对于poll、rtsig事件模块,Nginx会以有效句柄数预先建立ngx_connection_t结构, * 以加速事件收集、分发。这时,此成员保存所有ngx_connection_t指针组成的数组, * 下面的file_n表示指针总数,文件句柄值用来访问files成员 */ ngx_connection_t **files; /* 可用连接池,与free_connection_n(可用连接池中连接数目)配合使用 */ ngx_connection_t *free_connections; ngx_uint_t free_connection_n; /* 双向链表容器,元素类型是ngx_connection_t,表示可重复使用连接队列 */ ngx_queue_t reusable_connections_queue; /* 动态数组,数组元素存储着ngx_listening_t成员,表示监听端口及相关参数,下文着重介绍 */ ngx_array_t listening; /* * 动态数组容器,保存着Nginx所有要操作的目录 * 如果目录不存在,则试图创建,创建失败将导致Nginx启动失败 */ ngx_array_t paths; /* 单向链表容器,元素类型为ngx_open_file_t结构 * 表示Nginx已经打开所有文件。Nginx框架会在ngx_init_cycle中打开这些文件 */ ngx_list_t open_files; /* 单向链表容器,元素类型为ngx_shm_zone_t结构,每个元素表示一块共享内存。之后在Nginx进程间通信章节再学习 */ ngx_list_t shared_memory; /* 当前进程中所有连接对象的数目,与下面connections成员配合使用 */ ngx_uint_t connection_n; ngx_uint_t files_n; // files成员中已介绍 ngx_connection_t *connections; // 当前进程中的所有连接对象 ngx_event_t *read_events; // 当前进程中的所有读事件对象 ngx_event_t *write_events; // 当前进程中的所有写事件对象 /* * 旧的ngx_cycle_t对象用于引用上一个ngx_cycle_t对象中的成员。 * 举例:ngx_init_cycle方法在启动初期,需要建立一个临时的ngx_cycle_t对象保存一些变量, * 再调用ngx_init_cycle方法时就可以把旧的ngx_cycle_t传进去,此成员就保存前期的ngx_cycle_t对象 */ ngx_cycle_t *old_cycle; ngx_str_t conf_file; // Nginx配置文件相对于安装目录的路径名称 ngx_str_t conf_param; // Nginx处理配置文件时需要特殊处理的在命令行中携带的参数 ngx_str_t conf_prefix; // Nginx配置文件所在目录的路径 ngx_str_t prefix; // Nginx安装目录的路径 ngx_str_t lock_file; // 用于进程间同步的文件锁名称 ngx_str_t hostname; // 使用gethostname系统调用得到的主机名 };
ngx_listening_t结构体
Nginx作为一个Web服务器,首先需要监听端口并处理器中的网络事件,而监听端口这项工作在Nginx的启动框架代码中就已完成。上面ngx_cycle_t对象中有一个动态数组成员叫做listening,它的每个数组元素都是ngx_listening_t结构体。这样的一个结构体表示Nginx服务器监听的一个端口。
下面介绍下它的成员:
typedef struct ngx_listening_s ngx_listening_t; struct ngx_listening_s { ngx_socket_t fd; // socket句柄 struct sockaddr *sockaddr; // 监听socket地址 socklen_t socklen; // 地址长度 size_t addr_text_max_len; // 存储IP地址的字符串addr_text的最大长度,即指定其所分配的内存大小 ngx_str_t addr_text; // 字符串形式存储的IP地址 int type; // 套接字类型 /* TCP实现监听时的backlog队列,表示允许正在通过三次握手建立TCP连接但没有任何进程开始处理的最大连接数 */ int backlog; int rcvbuf; // 内核中对于当前套接字的接收缓冲区大小 int sndbuf; // 内核中对于当前套接字的发送缓冲区大小 #if (NGX_H***E_KEEPALIVE_TUNABLE) int keepidle; int keepintvl; int keepcnt; #endif /* handler of accepted connection */ ngx_connection_handler_pt handler; // 新的TCP连接成功建立后的处理方法 /* 保存当前对应着的所有主机名 */ void *servers; /* array of ngx_http_in_addr_t, for example */ /* 都是可用日志对象的指针 */ ngx_log_t log; ngx_log_t *logp; size_t pool_size; // 如果为新的TCP连接创建内存只,初始化大小为pool_size /* should be here because of the AcceptEx() preread */ size_t post_accept_buffer_size; /* should be here because of the deferred accept */ ngx_msec_t post_accept_timeout; // TCP连接建立成功后,经过此成员所对应的时间还没有接收到用户数据,则丢弃连接 ngx_listening_t *previous; // 前一个ngx_listening_t结构,单链表 ngx_connection_t *connection; // 当前监听句柄对应的ngx_connection_t结构体 /* 标志位 */ unsigned open:1; // 置1表示当前监听句柄有效,置0正常关闭 unsigned remain:1; // 置1表示使用已有的ngx_cycle_t来初始化ngx_cycle_t结构,原端口不关闭,置0表示正常关闭端口 unsigned ignore:1; // 置1表示跳过设置当前结构体中套接字成员,置0表示正常初始化套接字 unsigned bound:1; // 置1表示已经绑定,目前未使用 unsigned inherited:1; // 置1表示当前监听句柄来自前一个进程 unsigned nonblocking_accept:1; // 目前未使用 unsigned listen:1; // 置1表示当前结构体的套接字已经在监听 unsigned nonblocking:1; // 表示套接字是否阻塞,目前无意义 unsigned shared:1; // 表示在线程间共享,目前无意义 unsigned addr_ntop:1; // 置1表示Nginx需要将网络地址转变为字符串形式的地址 #if (NGX_H***E_INET6 && defined IPV6_V6ONLY) unsigned ipv6only:1; #endif unsigned keepalive:2; #if (NGX_H***E_DEFERRED_ACCEPT) unsigned deferred_accept:1; unsigned delete_deferred:1; unsigned add_deferred:1; #ifdef SO_ACCEPTFILTER char *accept_filter; #endif #endif #if (NGX_H***E_SETFIB) int setfib; #endif };其中,ngx_connection_handler_pt类型的handler成员在监听端口上成功建立新的TCP连接后,就会回调handler方法,定义如下:
typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);它接收一个ngx_connection_t连接参数,许多事件模块都会自定义handler方法。
ngx_cycle_t支持的方法
与ngx_cycle_t核心结构体相关的方式有很多,这里因为我自己还没有接触,只能在这先把与ngx_cycle_t相关的主要方法记录下,在后面的章节中再详细学习,以下方法都在ngx_cycle.c、ngx_process_cycle.c、ngx_event.c文件中。ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) | 返回初始化成功的完整的ngx_cycle_t结构体,包括初始化ngx_cycle_t中的成员,解析配置文件,加载所有模块,打开监听端口,初始化进程间通信方式等工作。失败则返回NULL指针 |
ngx_int_t ngx_process_options(ngx_cycle_t *cycle) | 用运行Nginx时可能携带的目录参数来初始化cycle,包括初始化运行目录,配置目录,并生成完整的nginx.conf配置文件路径 |
ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle) | 执行不重启服务升级Nginx时,新的Nginx进程通过此方法使用已经打开的TCP监听端口 |
ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) | 监听、绑定cycle中的listening动态数组指定的相应端口 |
void ngx_configure_listening_sockets(ngx_cycle_t *cycle) | 根据nginx.conf中的配置项设置已经监听的句柄 |
void ngx_close_listening_sockets(ngx_cycle_t *cycle) | 关闭cycle中的listening动态数组已经打开的端口 |
void ngx_master_process_cycle(ngx_cycle_t *cycle) | 进入master进程的工作循环 |
void ngx_single_process_cycle(ngx_cycle_t *cycle) | 进入单进程模式(非master、worker进程工作模式)的工作循环 |
void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type) | 启动n个worker子进程,并设置好每个子进程与master父进程之间使用socketpair系统调用建立起来的socke通信机制。 |
void ngx_start_cache_manager_processes(ngx_cycle_t *cycle, ngx_uint_t respawn) | 根据是否使用文件缓存模块,即cycle中存储路径的动态数组中manager标志是否打开,来决定是否启动cache manager子进程,根据loader标志决定是否启动cache loader进程 |
void ngx_pass_open_channel(ngx_cycle_t *cycle, ngx_channel_t *ch) | 向所有打开的channel发送ch消息 |
void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo) | 处理worker进程接收到的信号 |
ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle) | 检查master进程的所有子进程,根据每个子进程的状态(ngx_process_t结构体中的标志位)判断是否要启动子进程,更改pid文件等 |
void ngx_master_process_exit(ngx_cycle_t *cycle) | 退出master进程工作的循环 |
void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) | 进入worker进程工作的循环 |
void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_int_t worker) | 进入worker进程工作循环之前的初始化工作 |
void ngx_worker_process_exit(ngx_cycle_t *cycle) | 退出worke进程工作的循环 |
void ngx_cache_manager_process_cycle(ngx_cycle_t *cycle, void *data) | 执行缓存管理工作的循环方法 |
void ngx_process_events_and_timers(ngx_cycle_t *cycle) | 使用事件模块处理截止到现在已经收集到的事件 |
总结
全篇就记录一个东西ngx_cycle_t结构体。之后开始Nginx框架启动时的处理流程。主要参考
《深入理解Nginx》相关文章推荐
- spring核心框架体系结构(各个jar包作用)
- spring核心框架体系结构(各个jar包作用)
- 数据结构(十二)
- 基于proteus的51单片机仿真实例十二、51单片机的C语言程序结构
- 转:C#数据结构和算法学习系列十二----散列HashTable类
- Sharepoint2007核心表结构
- 用于核心模式驱动程序的网络体系结构(1)
- Launcher3 源码分析(一) 整体结构及核心类
- Python 核心编程笔记_Chapter_3 Note_2 模块结构布局
- ASP.NET MVC 项目结构与核心的DLL
- Spring3.1.0实现原理分析(十二).MVC核心类DispatcherServlet初始化过程
- Spring 核心框架体系结构
- Java核心技术(二) —— Java的基本程序设计结构
- 读jQuery之十二(删除事件核心方法)
- jQuery源码分析-03构造jQuery对象-源码结构和核心函数
- Linux核心数据结构
- Kafka源码深度解析-序列12 -Server核心组件之2-ReplicaManager核心数据结构与Replica同步原理
- CGAL几何库 半边网格数据结构 模板类 设计核心思想
- EXT核心API详解(十二)--GroupingStore/JsonStore/SimpleStore
- spring核心框架体系结构(各个jar包作用)