nginx解析

Nginx核心结构解析
本文详细介绍了Nginx中的重要结构体,包括nginx_cycle_t、nginx_conf_t、nginx_connection_t等,阐述了它们的功能及内部字段含义。此外,还概述了Nginx与PHP的交互过程。

重要的结构体

1. nginx_cycle_t

  1. struct ngx_cycle_s {  
  2.     void                  ****conf_ctx;  //配置上下文数组(含所有模块)  
  3.     ngx_pool_t               *pool;      //内存池  
  4.   
  5.     ngx_log_t                *log;       //日志  
  6.     ngx_log_t                 new_log;  
  7.   
  8.     ngx_connection_t        **files;     //连接文件  
  9.     ngx_connection_t         *free_connections;  //空闲连接  
  10.     ngx_uint_t                free_connection_n; //空闲连接个数  
  11.   
  12.     ngx_queue_t               reusable_connections_queue;  //再利用连接队列  
  13.   
  14.     ngx_array_t               listening;     //监听数组  
  15.     ngx_array_t               pathes;        //路径数组  
  16.     ngx_list_t                open_files;    //打开文件链表  
  17.     ngx_list_t                shared_memory; //共享内存链表  
  18.   
  19.     ngx_uint_t                connection_n;  //连接个数  
  20.     ngx_uint_t                files_n;       //打开文件个数  
  21.   
  22.     ngx_connection_t         *connections;   //连接  
  23.     ngx_event_t              *read_events;   //读事件  
  24.     ngx_event_t              *write_events;  //写事件  
  25.   
  26.     ngx_cycle_t              *old_cycle;     //old cycle指针  
  27.   
  28.     ngx_str_t                 conf_file;     //配置文件  
  29.     ngx_str_t                 conf_param;    //配置参数  
  30.     ngx_str_t                 conf_prefix;   //配置前缀  
  31.     ngx_str_t                 prefix;        //前缀  
  32.     ngx_str_t                 lock_file;     //锁文件  
  33.     ngx_str_t                 hostname;      //主机名  
  34. };  

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 :  内存池

  1. typedef struct {  
  2.    u_char      *last;  //当前内存池分配到此处,即下一次分配从此处开始  
  3.    u_char      *end;   //内存池结束位置  
  4.    ngx_pool_t  *next;  //内存池里面有很多块内存,这些内存块就是通过该指针连成链表的  
  5.    ngx_uint_t  failed; //内存池分配失败次数  
  6. } ngx_pool_data_t;    //内存池的数据块位置信息  
  7.  
  8. struct ngx_pool_s{    //内存池头部结构  
  9.    ngx_pool_data_t     d;       //内存池的数据块  
  10.    size_t              max;     //内存池数据块的最大值  
  11.    ngx_pool_t         *current; //指向当前内存池  
  12.    ngx_chain_t        *chain;   //该指针挂接一个ngx_chain_t结构  
  13.    ngx_pool_large_t   *large;   //大块内存链表,即分配空间超过max的内存  
  14.    ngx_pool_cleanup_t *cleanup; //释放内存池的callback  
  15.    ngx_log_t          *log;     //日志信息  
  16. };  

7. ngx_event_t :  每个事件都对应这样一个结构体

8. ngx_array_t :动态数组 (操作数组的几个API)

  1. struct ngx_array_s {  
  2.     void        *elts;    //数组数据区起始位置  
  3.     ngx_uint_t   nelts;   //实际存放的元素个数  
  4.     size_t       size;    //每个元素大小  
  5.     ngx_uint_t   nalloc;  //数组所含空间个数,即实际分配的小空间的个数  
  6.     ngx_pool_t  *pool;    //该数组在此内存池中分配  
  7. };  
  8.    
  9. typedef struct ngx_array_s  ngx_array_t;  

9. ngx_listending_t

  1. struct ngx_listening_s {  
  2.     ngx_socket_t        fd;//套接字句柄  
  3.   
  4.     struct sockaddr    *sockaddr;//监听sockaddr地址  
  5.     socklen_t           socklen;    /*sockaddr地址长度 size of sockaddr */  
  6.     size_t              addr_text_max_len;//存储ip地址的字符串addr_text最大长度  
  7.     ngx_str_t           addr_text;//以字符串形式存储ip地址  
  8.     //套接字类型。types是SOCK_STREAM时,表示是tcp  
  9.     int                 type;  
  10.     //TCP实现监听时的backlog队列,它表示允许正在通过三次握手建立tcp连接但还没有任何进程开始处理的连接最大个数  
  11.     int                 backlog;  
  12.     int                 rcvbuf;//套接字接收缓冲区大小  
  13.     int                 sndbuf;//套接字发送缓冲区大小  
  14.   
  15.     /* handler of accepted connection */  
  16.     ngx_connection_handler_pt   handler;//当新的tcp连接成功建立后的处理方法  
  17.     //目前主要用于HTTP或者mail等模块,用于保存当前监听端口对应着的所有主机名  
  18.     void               *servers;  /* array of ngx_http_in_addr_t, for example */  
  19.   
  20.     ngx_log_t           log;//日志  
  21.     ngx_log_t          *logp;//日志指针  
  22.   
  23.     size_t              pool_size;//如果为新的tcp连接创建内存池,则内存池的初始大小应该是pool_size。  
  24.     /* should be here because of the AcceptEx() preread */  
  25.     size_t              post_accept_buffer_size;  
  26.     /* should be here because of the deferred accept */  
  27.     ngx_msec_t          post_accept_timeout;//~秒后仍然没有收到用户的数据,就丢弃该连接  
  28.     //前一个ngx_listening_t结构,用于组成单链表  
  29.     ngx_listening_t    *previous;  
  30.     ngx_connection_t   *connection;//当前监听句柄对应的ngx_connection_t结构体  
  31.   
  32.     unsigned            open:1;//为1表示监听句柄有效,为0表示正常关闭  
  33.     unsigned            remain:1;//为1表示不关闭原先打开的监听端口,为0表示关闭曾经打开的监听端口  
  34.     unsigned            ignore:1;//为1表示跳过设置当前ngx_listening_t结构体中的套接字,为0时正常初始化套接字  
  35.   
  36.     unsigned            bound:1;       /* already bound */  
  37.     unsigned            inherited:1;   /* inherited from previous process */  
  38.     unsigned            nonblocking_accept:1;  
  39.     unsigned            listen:1;//为1表示当前结构体对应的套接字已经监听  
  40.     unsigned            nonblocking:1;  
  41.     unsigned            shared:1;    /* shared between threads or processes */  
  42.     unsigned            addr_ntop:1;//为1表示将网络地址转变为字符串形式的地址  
  43.   
  44. #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)  
  45.     unsigned            ipv6only:2;  
  46. #endif  
  47.   
  48. #if (NGX_HAVE_DEFERRED_ACCEPT)  
  49.     unsigned            deferred_accept:1;  
  50.     unsigned            delete_deferred:1;  
  51.     unsigned            add_deferred:1;  
  52. #ifdef SO_ACCEPTFILTER  
  53.     char               *accept_filter;  
  54. #endif  
  55. #endif  
  56. #if (NGX_HAVE_SETFIB)  
  57.     int                 setfib;  
  58. #endif  
  59.   
  60. };  

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值