ngx_buf_t

这个ngx_buf_t就是这个ngx_chain_t链表的每个节点的实际数据。该结构实际上是一种抽象的数据结构,它代表某种具体的数据。这个数据可能是指向内存中的某个缓冲区,也可能指向一个文件的某一部分,也可能是一些纯元数据(元数据的作用在于指示这个链表的读取者对读取的数据进行不同的处理)。

数据结构位于src/core/ngx_buf.h|c文件中。我们来看一下它的定义。

struct ngx_buf_s {
    u_char          *pos;
    u_char          *last;
    off_t            file_pos;
    off_t            file_last;

    u_char          *start;         /* start of buffer */
    u_char          *end;           /* end of buffer */
    ngx_buf_tag_t    tag;
    ngx_file_t      *file;
    ngx_buf_t       *shadow;


    /* the buf's content could be changed */
    unsigned         temporary:1;

    /*
     * the buf's content is in a memory cache or in a read only memory
     * and must not be changed
     */
    unsigned         memory:1;

    /* the buf's content is mmap()ed and must not be changed */
    unsigned         mmap:1;

    unsigned         recycled:1;
    unsigned         in_file:1;
    unsigned         flush:1;
    unsigned         sync:1;
    unsigned         last_buf:1;
    unsigned         last_in_chain:1;

    unsigned         last_shadow:1;
    unsigned         temp_file:1;

    /* STUB */ int   num;
};
  • pos:当buf所指向的数据在内存里的时候,pos指向的是这段数据开始的位置。
  • last:当buf所指向的数据在内存里的时候,last指向的是这段数据结束的位置。
  • file_pos:当buf所指向的数据是在文件里的时候,file_pos指向的是这段数据的开始位置在文件中的偏移量。
  • file_last:当buf所指向的数据是在文件里的时候,file_last指向的是这段数据的结束位置在文件中的偏移量。
  • start:当buf所指向的数据在内存里的时候,这一整块内存包含的内容可能被包含在多个buf中(比如在某段数据中间插入了其他的数据,这一块数据就需要被拆分开)。那么这些buf中的start和end都指向这一块内存的开始地址和结束地址。而pos和last指向本buf所实际包含的数据的开始和结尾。
  • end:解释参见start。
  • tag:实际上是一个void*类型的指针,使用者可以关联任意的对象上去,只要对使用者有意义。
  • file:当buf所包含的内容在文件中时,file字段指向对应的文件对象。
  • shadow:当这个buf完整copy了另外一个buf的所有字段的时候,那么这两个buf指向的实际上是同一块内存,或者是同一个文件的同一部分,此时这两个buf的shadow字段都是指向对方的。那么对于这样的两个buf,在释放的时候,就需要使用者特别小心,具体是由哪里释放,要提前考虑好,如果造成资源的多次释放,可能会造成程序崩溃!
  • temporary:为1时表示该buf所包含的内容是在一个用户创建的内存块中,并且可以被在filter处理的过程中进行变更,而不会造成问题。
  • memory:为1时表示该buf所包含的内容是在内存中,但是这些内容却不能被进行处理的filter进行变更。
  • mmap:为1时表示该buf所包含的内容是在内存中, 是通过mmap使用内存映射从文件中映射到内存中的,这些内容却不能被进行处理的filter进行变更。
  • recycled:可以回收的。也就是这个buf是可以被释放的。这个字段通常是配合shadow字段一起使用的,对于使用ngx_create_temp_buf 函数创建的buf,并且是另外一个buf的shadow,那么可以使用这个字段来标示这个buf是可以被释放的。
  • in_file:为1时表示该buf所包含的内容是在文件中。
  • flush:遇到有flush字段被设置为1的的buf的chain,则该chain的数据即便不是最后结束的数据(last_buf被设置,标志所有要输出的内容都完了),也会进行输出,不会受postpone_output配置的限制,但是会受到发送速率等其他条件的限制。
  • last_buf:数据被以多个chain传递给了过滤器,此字段为1表明这是最后一个buf。
  • last_in_chain:在当前的chain里面,此buf是最后一个。特别要注意的是last_in_chain的buf不一定是last_buf,但是last_buf的buf一定是last_in_chain的。这是因为数据会被以多个chain传递给某个filter模块。
  • last_shadow:在创建一个buf的shadow的时候,通常将新创建的一个buf的last_shadow置为1。
  • temp_file:由于受到内存使用的限制,有时候一些buf的内容需要被写到磁盘上的临时文件中去,那么这时,就设置此标志 。

对于此对象的创建,可以直接在某个ngx_pool_t上分配,然后根据需要,给对应的字段赋值。也可以使用定义好的2个宏:

#define ngx_alloc_buf(pool)  ngx_palloc(pool, sizeof(ngx_buf_t))
#define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t))

这两个宏使用类似函数,也是不说自明的。

对于创建temporary字段为1的buf(就是其内容可以被后续的filter模块进行修改),可以直接使用函数ngx_create_temp_buf进行创建。

ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size);

该函数创建一个ngx_but_t类型的对象,并返回指向这个对象的指针,创建失败返回NULL。

对于创建的这个对象,它的start和end指向新分配内存开始和结束的地方。pos和last都指向这块新分配内存的开始处,这样,后续的操作可以在这块新分配的内存上存入数据。

  • pool:分配该buf和buf使用的内存所使用的pool。
  • size:该buf使用的内存的大小。

为了配合对ngx_buf_t的使用,nginx定义了以下的宏方便操作。

#define ngx_buf_in_memory(b)        (b->temporary || b->memory || b->mmap)

返回这个buf里面的内容是否在内存里。

#define ngx_buf_in_memory_only(b)   (ngx_buf_in_memory(b) && !b->in_file)

返回这个buf里面的内容是否仅仅在内存里,并且没有在文件里。

#define ngx_buf_special(b)                                                   \
    ((b->flush || b->last_buf || b->sync)                                    \
     && !ngx_buf_in_memory(b) && !b->in_file)

返回该buf是否是一个特殊的buf,只含有特殊的标志和没有包含真正的数据。

#define ngx_buf_sync_only(b)                                                 \
    (b->sync                                                                 \
     && !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf)

返回该buf是否是一个只包含sync标志而不包含真正数据的特殊buf。

#define ngx_buf_size(b)                                                      \
    (ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos):                      \
                            (b->file_last - b->file_pos))

返回该buf所含数据的大小,不管这个数据是在文件里还是在内存里。