Skip to content

Instantly share code, notes, and snippets.

@JeOam
Created December 15, 2015 09:59
Show Gist options
  • Save JeOam/fca30ae150a6f8f03475 to your computer and use it in GitHub Desktop.
Save JeOam/fca30ae150a6f8f03475 to your computer and use it in GitHub Desktop.
Nginx 数据结构和方法
@JeOam
Copy link
Author

JeOam commented Dec 15, 2015

key/value 对 => ngx_table_elt_t

typedef struct{
        ngx_uint_t hash;  // 快速检索
        ngx_str_t key;
        ngx_str_t value;
        u_char *lowcase_key;  // 全小写的 key 字符串
}ngx_table_elt_t;

@JeOam
Copy link
Author

JeOam commented Dec 15, 2015

缓冲区相关的数据结构:ngx_buf_t

typedef struct ngx_buf_s ngx_buf_t;
typedef void *ngx_buf_tag_t;
struct ngx_buf_s{
        /*pos通常是用来告诉使用者本次应该从pos这个位置开始处理内存中的数据, 这样设置是因为同一个ngx_buf_t可能被多次反复处理。当然, pos的含义是由使用它的模块定义的*/
        u_char *pos;
        /*last通常表示有效的内容到此为止, 注意, pos与last之间的内存是希望nginx处理的内容*/
        u_char *last;
        /*处理文件时, file_pos与file_last的含义与处理内存时的pos与last相同, file_pos表示将要处理的文件位置, file_last表示截止的文件位置*/
        off_t file_pos;
        off_t file_last;
        //如果ngx_buf_t缓冲区用于内存, 那么start指向这段内存的起始地址
        u_char *start;
        //与start成员对应, 指向缓冲区内存的末尾
        u_char *end;
        /*表示当前缓冲区的类型, 例如由哪个模块使用就指向这个模块ngx_module_t变量的地址*/
        ngx_buf_tag_t tag;
        //引用的文件
        ngx_file_t *file;
        /*当前缓冲区的影子缓冲区, 该成员很少用到, 仅仅在12.8节描述的使用缓冲区转发上游服务器的响应时才使用了shadow成员, 这是因为Nginx太节约内存了, 分配一块内存并使用ngx_buf_t表示接收到的上游服务器响应后, 在向下游客户端转发时可能会把这块内存存储到文件中, 也可能直接向下游发送, 此时Nginx绝不会重新复制一份内存用于新的目的, 而是再次建立一个ngx_buf_t结构体指向原内存, 这样多个ngx_buf_t结构体指向了同一块内存, 它们之间的关系就通过shadow成员来引用。这种设计过于复杂, 通常不建议使用*/
        ngx_buf_t *shadow;
        //临时内存标志位, 为1时表示数据在内存中且这段内存可以修改
        unsigned temporary:1;
        //标志位, 为1时表示数据在内存中且这段内存不可以被修改
        unsigned memory:1;
        //标志位, 为1时表示这段内存是用mmap系统调用映射过来的, 不可以被修改
        unsigned mmap:1;
        //标志位, 为1时表示可回收
        unsigned recycled:1;
        //标志位, 为1时表示这段缓冲区处理的是文件而不是内存
        unsigned in_file:1;
        //标志位, 为1时表示需要执行flush操作
        unsigned flush:1;
        /*标志位, 对于操作这块缓冲区时是否使用同步方式, 需谨慎考虑, 这可能会阻塞Nginx进程, Nginx中所有操作几乎都是异步的, 这是它支持高并发的关键。有些框架代码在sync为1时可能会有阻塞的方式进行I/O操作, 它的意义视使用它的Nginx模块而定*/
        unsigned sync:1;
        /*标志位, 表示是否是最后一块缓冲区, 因为ngx_buf_t可以由ngx_chain_t链表串联起来, 因此, 当last_buf为1时, 表示当前是最后一块待处理的缓冲区*/
        unsigned last_buf:1;
        //标志位, 表示是否是ngx_chain_t中的最后一块缓冲区
        unsigned last_in_chain:1;
        /*标志位, 表示是否是最后一个影子缓冲区, 与shadow域配合使用。通常不建议使用它*/
        unsigned last_shadow:1;
        //标志位, 表示当前缓冲区是否属于临时文件
        unsigned temp_file:1;
};

@JeOam
Copy link
Author

JeOam commented Dec 15, 2015

ngx_chain_t 是与 ngx_buf_t 配合使用的链表数据结构

typedef struct ngx_chain_s ngx_chain_t;
struct ngx_chain_s{
        ngx_buf_t *buf;  // 指向当前的 ngx_buf_t 缓冲区
        ngx_chain_t *next;  // 指向下一个ngx_chain_t。如果这是最后一个ngx_chain_t,则需要把next置为NULL。
}; 

在向用户发送 HTTP 包体时,就要传入 ngx_chain_t 链表对象,注意,如果是最后一个 ngx_chain_t,那么必须将 next 置为 NULL,否则永远不会发送成功,而且这个请求将一直不会结束(Nginx框架的要求)。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment