重要的结构体
1. nginx_cycle_t
- struct ngx_cycle_s {
- void ****conf_ctx; //配置上下文数组(含所有模块)
- ngx_pool_t *pool; //内存池
- ngx_log_t *log; //日志
- ngx_log_t new_log;
- ngx_connection_t **files; //连接文件
- ngx_connection_t *free_connections; //空闲连接
- ngx_uint_t free_connection_n; //空闲连接个数
- ngx_queue_t reusable_connections_queue; //再利用连接队列
- ngx_array_t listening; //监听数组
- ngx_array_t pathes; //路径数组
- ngx_list_t open_files; //打开文件链表
- ngx_list_t shared_memory; //共享内存链表
- ngx_uint_t connection_n; //连接个数
- ngx_uint_t files_n; //打开文件个数
- ngx_connection_t *connections; //连接
- ngx_event_t *read_events; //读事件
- ngx_event_t *write_events; //写事件
- ngx_cycle_t *old_cycle; //old cycle指针
- ngx_str_t conf_file; //配置文件
- ngx_str_t conf_param; //配置参数
- ngx_str_t conf_prefix; //配置前缀
- ngx_str_t prefix; //前缀
- ngx_str_t lock_file; //锁文件
- ngx_str_t hostname; //主机名
- };
2. nginx_conf_t
struct ngx_conf_s {
char *name;
ngx_array_t *args;//每解析一行,从配置文件中解析出的配置项全部在这里面
//最终指向的是一个全局类型的ngx_cycle_s,即ngx_cycle,见ngx_init_cycle
ngx_cycle_t *cycle; //指向对应的cycle,见ngx_init_cycle中的两行conf.ctx = cycle->conf_ctx; conf.cycle = cycle;
ngx_pool_t *pool;
ngx_pool_t *temp_pool; //用该poll的空间都是临时空间,最终在ngx_init_cycle->ngx_destroy_pool(conf.temp_pool);中释放
ngx_conf_file_t *conf_file; //nginx.conf
ngx_log_t *log;
//cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
//指向ngx_cycle_t->conf_ctx 有多少个模块,就有多少个ctx指针数组成员 conf.ctx = cycle->conf_ctx;见ngx_init_cycle
//这个ctx每次在在进入对应的server{} location{}前都会指向零时保存父级的ctx,该{}解析完后在恢复到父的ctx。可以参考ngx_http_core_server,ngx_http_core_location
void *ctx;//指向结构ngx_http_conf_ctx_t ngx_core_module_t ngx_event_module_t ngx_stream_conf_ctx_t等
ngx_uint_t module_type;
//表示当前配置项是属于那个大类模块 取值有如下5种:NGX_HTTP_MODULE、NGX_CORE_MODULE、NGX_CONF_MODULE、NGX_EVENT_MODULE、NGX_MAIL_MODULE
ngx_uint_t cmd_type; //大类里面的那个子类模块,如NGX_HTTP_SRV_CONF NGX_HTTP_LOC_CONF等
ngx_conf_handler_pt handler;
char *handler_conf;
};3. nginx_connection_t : 每个连接都对应这样一个结构体
4. nginx_buf_t
struct ngx_buf_s { //可以参考ngx_create_temp_buf 函数空间在ngx_create_temp_buf创建,让指针指向这些空间
/*pos通常是用来告诉使用者本次应该从pos这个位置开始处理内存中的数据,这样设置是因为同一个ngx_buf_t可能被多次反复处理。
当然,pos的含义是由使用它的模块定义的*/
//它的pos成员和last成员指向的地址之间的内存就是接收到的还未解析的字符流
u_char *pos; //pos指针指向从内存池里分配的内存。 pos为已扫描的内存端中,还未解析的内存的尾部,
u_char *last;/*last通常表示有效的内容到此为止,注意,pos与last之间的内存是希望nginx处理的内容*/
/* 处理文件时,file_pos与file_last的含义与处理内存时的pos与last相同,file_pos表示将要处理的文件位置,file_last表示截止的文件位置 */
off_t file_pos; //可以结合ngx_output_chain_copy_buf阅读更好理解 输出数据的打印可以在ngx_http_write_filter中查看调试信息
//也就是实际存到临时文件中的字节数,见ngx_event_pipe_write_chain_to_temp_file
off_t file_last; //写入文件内容的最尾处的长度赋值见ngx_http_read_client_request_body 输出数据的打印可以在ngx_http_write_filter中查看调试信息
//如果ngx_buf_t缓冲区用于内存,那么start指向这段内存的起始地址
u_char *start; /* start of buffer */ //创建空间见ngx_http_upstream_process_header
u_char *end; /* end of buffer */ //与start成员对应,指向缓冲区内存的末尾
//ngx_http_request_body_length_filter中赋值为ngx_http_read_client_request_body
//实际上是一个void*类型的指针,使用者可以关联任意的对象上去,只要对使用者有意义。
ngx_buf_tag_t tag;/*表示当前缓冲区的类型,例如由哪个模块使用就指向这个模块ngx_module_t变量的地址*/
ngx_file_t *file;//引用的文件 用于存储接收到所有包体后,把包体内容写入到file文件中,赋值见ngx_http_read_client_request_body
/*当前缓冲区的影子缓冲区,该成员很少用到,仅仅在使用缓冲区转发上游服务器的响应时才使用了shadow成员,这是因为Nginx太节
约内存了,分配一块内存并使用ngx_buf_t表示接收到的上游服务器响应后,在向下游客户端转发时可能会把这块内存存储到文件中,也
可能直接向下游发送,此时Nginx绝不会重新复制一份内存用于新的目的,而是再次建立一个ngx_buf_t结构体指向原内存,这样多个
ngx_buf_t结构体指向了同一块内存,它们之间的关系就通过shadow成员来引用。这种设计过于复杂,通常不建议使用
当这个buf完整copy了另外一个buf的所有字段的时候,那么这两个buf指向的实际上是同一块内存,或者是同一个文件的同一部分,此
时这两个buf的shadow字段都是指向对方的。那么对于这样的两个buf,在释放的时候,就需要使用者特别小心,具体是由哪里释放,要
提前考虑好,如果造成资源的多次释放,可能会造成程序崩溃!
*/
ngx_buf_t *shadow; //参考ngx_http_fastcgi_input_filter
/* the buf's content could be changed */
//为1时表示该buf所包含的内容是在一个用户创建的内存块中,并且可以被在filter处理的过程中进行变更,而不会造成问题
unsigned temporary:1; //临时内存标志位,为1时表示数据在内存中且这段内存可以修改
/*
* the buf's content is in a memory cache or in a read only memory
* and must not be changed
*/ //为1时表示该buf所包含的内容是在内存中,但是这些内容确不能被进行处理的filter进行变更。
unsigned memory:1;//标志位,为1时表示数据在内存中且这段内存不可以被修改
/* the buf's content is mmap()ed and must not be changed */
//为1时表示该buf所包含的内容是在内存中, 是通过mmap使用内存映射从文件中映射到内存中的,这些内容确不能被进行处理的filter进行变更。
unsigned mmap:1;//标志位,为1时表示这段内存是用mmap系统调用映射过来的,不可以被修改
//可以回收的。也就是这个buf是可以被释放的。这个字段通常是配合shadow字段一起使用的,对于使用ngx_create_temp_buf 函数创建的buf,
//并且是另外一个buf的shadow,那么可以使用这个字段来标示这个buf是可以被释放的。
//置1了表示该buf需要马上发送出去,参考ngx_http_write_filter -> if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
unsigned recycled:1; //标志位,为1时表示可回收利用,当该buf被新的buf指针指向的时候,就置1,见ngx_http_upstream_send_response
/*
ngx_buf_t有一个标志位in_file,将in_file置为1就表示这次ngx_buf_t缓冲区发送的是文件而不是内存。
调用ngx_http_output_filter后,若Nginx检测到in_file为1,将会从ngx_buf_t缓冲区中的file成员处获取实际的文件。file的类型是ngx_file_t
*/ //为1时表示该buf所包含的内容是在文件中。 输出数据的打印可以在ngx_http_write_filter中查看调试信息
unsigned in_file:1;//标志位,为1时表示这段缓冲区处理的是文件而不是内存,说明包体全部存入文件中,需要配置"client_body_in_file_only" on | clean
//遇到有flush字段被设置为1的的buf的chain,则该chain的数据即便不是最后结束的数据(last_buf被设置,标志所有要输出的内容都完了),
//也会进行输出,不会受postpone_output配置的限制,但是会受到发送速率等其他条件的限制。
////置1了表示该buf需要马上发送出去,参考ngx_http_write_filter -> if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
unsigned flush:1;//标志位,为1时表示需要执行flush操作 标示需要立即发送缓冲的所有数据;
/*标志位,对于操作这块缓冲区时是否使用同步方式,需谨慎考虑,这可能会阻塞Nginx进程,Nginx中所有操作几乎都是异步的,这是
它支持高并发的关键。有些框架代码在sync为1时可能会有阻塞的方式进行I/O操作,它的意义视使用它的Nginx模块而定*/
unsigned sync:1;
/*标志位,表示是否是最后一块缓冲区,因为ngx_buf_t可以由ngx_chain_t链表串联起来,因此,当last_buf为1时,表示当前是最后一块待处理的缓冲区*/
/*
如果接受包体接收完成,则存储最后一个包体内容的buf的last_buf置1,见ngx_http_request_body_length_filter
如果发送包体的时候只有头部,这里会置1,见ngx_http_header_filter
如果各个模块在发送包体内容的时候,如果送入ngx_http_write_filter函数的in参数chain表中的某个buf为该包体的最后一段内容,则该buf中的last_buf会置1
*/ // ngx_http_send_special中会置1 见ngx_http_write_filter -> if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
//置1了表示该buf需要马上发送出去,参考ngx_http_write_filter -> if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
unsigned last_buf:1; //数据被以多个chain传递给了过滤器,此字段为1表明这是最后一个chain。
//在当前的chain里面,此buf是最后一个。特别要注意的是last_in_chain的buf不一定是last_buf,但是last_buf的buf一定是last_in_chain的。这是因为数据会被以多个chain传递给某个filter模块。
unsigned last_in_chain:1;//标志位,表示是否是ngx_chain_t中的最后一块缓冲区
//在创建一个buf的shadow的时候,通常将新创建的一个buf的last_shadow置为1。
//参考ngx_http_fastcgi_input_filter
//当数据被发送出去后,该标志位1的ngx_buf_t最终会添加到free_raw_bufs中
//该值一般都为1,
unsigned last_shadow:1; /*标志位,表示是否是最后一个影子缓冲区,与shadow域配合使用。通常不建议使用它*/
unsigned temp_file:1;//标志位,表示当前缓冲区是否属于临时文件
/* STUB */ int num; //是为读取后端服务器包体分配的第几个buf ,见ngx_event_pipe_read_upstream 表示属于链表chain中的第几个buf
};
5. nginx_request_t : 一个请求对应一个 nginx_request_t 结构体
6. ngx_pool_t : 内存池
- typedef struct {
- u_char *last; //当前内存池分配到此处,即下一次分配从此处开始
- u_char *end; //内存池结束位置
- ngx_pool_t *next; //内存池里面有很多块内存,这些内存块就是通过该指针连成链表的
- ngx_uint_t failed; //内存池分配失败次数
- } ngx_pool_data_t; //内存池的数据块位置信息
- struct ngx_pool_s{ //内存池头部结构
- ngx_pool_data_t d; //内存池的数据块
- size_t max; //内存池数据块的最大值
- ngx_pool_t *current; //指向当前内存池
- ngx_chain_t *chain; //该指针挂接一个ngx_chain_t结构
- ngx_pool_large_t *large; //大块内存链表,即分配空间超过max的内存
- ngx_pool_cleanup_t *cleanup; //释放内存池的callback
- ngx_log_t *log; //日志信息
- };
7. ngx_event_t : 每个事件都对应这样一个结构体
8. ngx_array_t :动态数组 (操作数组的几个API)
- struct ngx_array_s {
- void *elts; //数组数据区起始位置
- ngx_uint_t nelts; //实际存放的元素个数
- size_t size; //每个元素大小
- ngx_uint_t nalloc; //数组所含空间个数,即实际分配的小空间的个数
- ngx_pool_t *pool; //该数组在此内存池中分配
- };
- typedef struct ngx_array_s ngx_array_t;
9. ngx_listending_t
- struct ngx_listening_s {
- ngx_socket_t fd;//套接字句柄
- struct sockaddr *sockaddr;//监听sockaddr地址
- socklen_t socklen; /*sockaddr地址长度 size of sockaddr */
- size_t addr_text_max_len;//存储ip地址的字符串addr_text最大长度
- ngx_str_t addr_text;//以字符串形式存储ip地址
- //套接字类型。types是SOCK_STREAM时,表示是tcp
- int type;
- //TCP实现监听时的backlog队列,它表示允许正在通过三次握手建立tcp连接但还没有任何进程开始处理的连接最大个数
- int backlog;
- int rcvbuf;//套接字接收缓冲区大小
- int sndbuf;//套接字发送缓冲区大小
- /* handler of accepted connection */
- ngx_connection_handler_pt handler;//当新的tcp连接成功建立后的处理方法
- //目前主要用于HTTP或者mail等模块,用于保存当前监听端口对应着的所有主机名
- 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;//~秒后仍然没有收到用户的数据,就丢弃该连接
- //前一个ngx_listening_t结构,用于组成单链表
- ngx_listening_t *previous;
- ngx_connection_t *connection;//当前监听句柄对应的ngx_connection_t结构体
- unsigned open:1;//为1表示监听句柄有效,为0表示正常关闭
- unsigned remain:1;//为1表示不关闭原先打开的监听端口,为0表示关闭曾经打开的监听端口
- unsigned ignore:1;//为1表示跳过设置当前ngx_listening_t结构体中的套接字,为0时正常初始化套接字
- unsigned bound:1; /* already bound */
- unsigned inherited:1; /* inherited from previous process */
- unsigned nonblocking_accept:1;
- unsigned listen:1;//为1表示当前结构体对应的套接字已经监听
- unsigned nonblocking:1;
- unsigned shared:1; /* shared between threads or processes */
- unsigned addr_ntop:1;//为1表示将网络地址转变为字符串形式的地址
- #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
- unsigned ipv6only:2;
- #endif
- #if (NGX_HAVE_DEFERRED_ACCEPT)
- unsigned deferred_accept:1;
- unsigned delete_deferred:1;
- unsigned add_deferred:1;
- #ifdef SO_ACCEPTFILTER
- char *accept_filter;
- #endif
- #endif
- #if (NGX_HAVE_SETFIB)
- int setfib;
- #endif
- };
10 ngx_socket_t : int
11. ngx_list_t : 链表
12. ngx_queue_t : 队列
13. ngx_path_t:
typedef struct {
//fastcgi_cache_path /tmp/nginx/fcgi/cache levels=1:2 keys_zone=fcgi:10m inactive=30m max_size=128m;中的levels=1:2中的1:2中的/tmp/nginx/fcgi/cache
ngx_str_t name; //路径名
//可以参考下ngx_create_hashed_filename
size_t len; //levels=x:y最终的结果是path->len = (x+1) + (y+1) 参考ngx_http_file_cache_set_slot
/*
levels=1:2,意思是说使用两级目录,第一级目录名是一个字符,第二级用两个字符。但是nginx最大支持3级目录,即levels=xxx:xxx:xxx。
那么构成目录名字的字符哪来的呢?假设我们的存储目录为/cache,levels=1:2,那么对于上面的文件 就是这样存储的:
/cache/0/8d/8ef9229f02c5672c747dc7a324d658d0 注意后面的8d0和cache后面的/0/8d一致 参考ngx_create_hashed_filename
*/ //fastcgi_cache_path /tmp/nginx/fcgi/cache levels=1:2 keys_zone=fcgi:10m inactive=30m max_size=128m;中的levels=1:2中的1:2
//目录创建见ngx_create_path
//一个对应的缓存文件的目录f/27/46492fbf0d9d35d3753c66851e81627f中的46492fbf0d9d35d3753c66851e81627f,注意f/27就是最尾部的字节,这个由levle=1:2,就是最后面的1个字节+2个字节
size_t level[3]; //把levels=x:y;中的x和y分别存储在level[0]和level[1] level[3]始终为0
//ngx_http_file_cache_set_slot中设置为ngx_http_file_cache_manager
//一般只有涉及到共享内存分配管理的才有该pt,例如fastcgi_cache_path xxx keys_zone=fcgi:10m xxx 只要有这些配置则会启用cache进程,见ngx_start_cache_manager_processes
ngx_path_manager_pt manager; //ngx_cache_manager_process_handler中执行
//manger和loader。是cache管理回调函数
//ngx_http_file_cache_set_slot中设置为ngx_http_file_cache_loader ngx_cache_loader_process_handler中执行
ngx_path_loader_pt loader; //决定是否启用cache loader进程 参考ngx_start_cache_manager_processes
void *data; //ngx_http_file_cache_set_slot中设置为ngx_http_file_cache_t
u_char *conf_file; //所在的配置文件 见ngx_http_file_cache_set_slot
ngx_uint_t line; //在配置文件中的行号,见ngx_http_file_cache_set_slot
} ngx_path_t;14. ngx_module_t
struct ngx_module_s {
ngx_uint_t ctx_index; // ctx index表明了模块在相同类型模块中的顺序
/*分类的模块计数器
nginx模块可以分为四种:core、event、http和mail
每个模块都会各自计数,ctx_index就是每个模块在其所属类组的计数*/
ngx_uint_t index;
/*一个模块计数器,按照每个模块在ngx_modules[]数组中的声明顺序,从0开始依次给每个模块赋值*/
ngx_uint_t spare0;
ngx_uint_t spare1;
ngx_uint_t spare2;
ngx_uint_t spare3;
ngx_uint_t version; //nginx模块版本
void *ctx;
/*模块的上下文,不同种类的模块有不同的上下文,因此实现了四种结构体*/
ngx_command_t *commands;
/*命令定义地址
模块的指令集
每一个指令在源码中对应着一个ngx_command_t结构变量*/
ngx_uint_t type; //模块类型,用于区分core event http和mail
ngx_int_t (*init_master)(ngx_log_t *log); //初始化master时执行
ngx_int_t (*init_module)(ngx_cycle_t *cycle); //初始化module时执行
ngx_int_t (*init_process)(ngx_cycle_t *cycle); //初始化process时执行
ngx_int_t (*init_thread)(ngx_cycle_t *cycle); //初始化thread时执行
void (*exit_thread)(ngx_cycle_t *cycle); //退出thread时执行
void (*exit_process)(ngx_cycle_t *cycle); //退出process时执行
void (*exit_master)(ngx_cycle_t *cycle); //退出master时执行
//以下功能不明
uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};15. ngx_core_conf_t
typedef struct { //从ngx_cycle_s->conf_ctx[ngx_core_module.index]指向这里
ngx_flag_t daemon;
ngx_flag_t master; //在ngx_core_module_init_conf中初始化为1 通过参数"master_process"设置
ngx_msec_t timer_resolution; //从timer_resolution全局配置中解析到的参数,表示多少ms执行定时器中断,然后epoll_wail会返回跟新内存时间
ngx_int_t worker_processes; //创建的worker进程数,通过nginx配置,默认为1 "worker_processes"设置
ngx_int_t debug_points;
//修改工作进程的打开文件数的最大值限制(RLIMIT_NOFILE),用于在不重启主进程的情况下增大该限制。
ngx_int_t rlimit_nofile;
//修改工作进程的core文件尺寸的最大值限制(RLIMIT_CORE),用于在不重启主进程的情况下增大该限制。
off_t rlimit_core;//worker_rlimit_core 1024k; coredump文件大小
int priority;
/*
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000; 四个工作进程分别在四个指定的he上面运行
如果是5he可以这样配置
worker_cpu_affinity 00001 00010 00100 01000 10000; 其他多核类似
*/ //参考ngx_set_cpu_affinity
ngx_uint_t cpu_affinity_n; //worker_cpu_affinity参数个数
uint64_t *cpu_affinity;//worker_cpu_affinity 00001 00010 00100 01000 10000;转换的位图结果就是0X11111
char *username;
ngx_uid_t user;
ngx_gid_t group;
ngx_str_t working_directory;//working_directory /var/yyz/corefile/; coredump存放路径
ngx_str_t lock_file;
ngx_str_t pid; //默认NGX_PID_PATH,主进程名
ngx_str_t oldpid;//NGX_PID_PATH+NGX_OLDPID_EXT 热升级nginx进程的时候用
//数组第一个成员是TZ字符串
ngx_array_t env;//成员类型ngx_str_t,见ngx_core_module_create_conf
char **environment; //直接指向env,见ngx_set_environment
} ngx_core_conf_t;16. ngx_conf_file_t
typedef struct { //对应的是核心模块NGX_CORE_MODULE,在ngx_init_cycle中执行
ngx_str_t name;
void *(*create_conf)(ngx_cycle_t *cycle);
//它还提供了init_conf回调方法,用于在解析完配置文件后,使用解析出的配置项初始化核心模块功能。
char *(*init_conf)(ngx_cycle_t *cycle, void *conf);
} ngx_core_module_t;
typedef struct {
ngx_file_t file; //配置文件名
ngx_buf_t *buffer; //文件内容在这里面存储
//当在解析从文件中读取到的4096字节内存时,如果最后面的内存不足以构成一个token,
//则把这部分内存零时存起来,然后拷贝到下一个4096内存的头部参考ngx_conf_read_token
ngx_buf_t *dump;
ngx_uint_t line; //在配置文件中的行号 可以参考ngx_thread_pool_add
} ngx_conf_file_t;二、 nginx中重要的数据结构
三、 nginx与php交互的过程: https://blog.youkuaiyun.com/misakaqunianxiatian/article/details/52651071
本文详细介绍了Nginx中的重要结构体,包括nginx_cycle_t、nginx_conf_t、nginx_connection_t等,阐述了它们的功能及内部字段含义。此外,还概述了Nginx与PHP的交互过程。
1390

被折叠的 条评论
为什么被折叠?



