Nginx-ngx_buf

    Nginx中关于缓冲区的相关操作全部在ngx_buf这个源代码文件里, 先来看看buf涉及到的数据结构。

typedef void *            ngx_buf_tag_t;

typedef struct ngx_buf_s  ngx_buf_t;

struct ngx_buf_s {
    u_char          *pos;
    u_char          *last; //buffer当前使用到的位置
    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;
};


struct ngx_chain_s {
    ngx_buf_t    *buf;
    ngx_chain_t  *next;
};
在ngx_buf_t中涉及到多个位域,基本都是用于标志位,这里先不做详细的解释。 先来看看基本基本的函数。

ngx_buf_t *
ngx_create_temp_buf(ngx_pool_t *pool, size_t size)
{
    ngx_buf_t *b; 
    //#define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t))
    b = ngx_calloc_buf(pool);
    if (b == NULL) {
        return NULL;
    }   
    //初始化buf的起始指针,为buf申请空降
    b->start = ngx_palloc(pool, size);
    if (b->start == NULL) {
        return NULL;
    }   

    /*  
     * set by ngx_calloc_buf():
     *
     *     b->file_pos = 0;
     *     b->file_last = 0;
     *     b->file = NULL;
     *     b->shadow = NULL;
     *     b->tag = 0;
     *     and flags
     */

    b->pos = b->start;
    b->last = b->start;
    b->end = b->last + size;  
    b->temporary = 1;

    return b;
}
再来看下关于创建buffer链表的接口函数
ngx_chain_t *
ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
{
    u_char       *p;
    ngx_int_t     i;
    ngx_buf_t    *b;
    ngx_chain_t  *chain, *cl, **ll;
    //申请链表所需要的总空间
    p = ngx_palloc(pool, bufs->num * bufs->size);
    if (p == NULL) {
        return NULL;
    }

    ll = &chain;
    //逐个处理各个buf,主要是初始化和建立链表
    for (i = 0; i < bufs->num; i++) {
        //buf本身需要的空间申请
        b = ngx_calloc_buf(pool);
        if (b == NULL) {
            return NULL;
        }
  /*
         * set by ngx_calloc_buf():
         *
         *     b->file_pos = 0;
         *     b->file_last = 0;
         *     b->file = NULL;
         *     b->shadow = NULL;
         *     b->tag = 0;
         *     and flags
         *
         */

        b->pos = p;
        b->last = p;
        b->temporary = 1;
        //buffer数据区指针初始化
        b->start = p;
        p += bufs->size;
        b->end = p;
        //从pool中申请一个ngx_chain_t节点的空间
        cl = ngx_alloc_chain_link(pool);
        if (cl == NULL) {
            return NULL;
        }

        cl->buf = b;
        *ll = cl;
        ll = &cl->next;    
    }

    *ll = NULL;
    //最后返回链表的头节点。
    return chain;
}                
上面这个函数里用到了 ngx_alloc_chain_link这函数,这个函数的主要功能是从pool中申请一个ngx_chain_t的结构体空间。

ngx_chain_t *
ngx_alloc_chain_link(ngx_pool_t *pool)
{
    ngx_chain_t  *cl;

    cl = pool->chain;
    //当pool中有chain节点的时候,直接拿出来用,就不需要重新申请了。
    if (cl) {
        pool->chain = cl->next;
        return cl;
    }
    //pool中的chain节点用完了,那么需要从pool中重新申请
    cl = ngx_palloc(pool, sizeof(ngx_chain_t));
    if (cl == NULL) {
        return NULL;
    }

    return cl;
}

实际上这个函数就是从pool中的chain链表中去拿节点,没有了那么需要从内存池子中去申请。

对应于上一个申请空间的函数,那么还有一个回收空间的函数,不过这里是采用宏定义的方式实现的:

#define ngx_free_chain(pool, cl)                                             \
    cl->next = pool->chain;                                                  \
    pool->chain = cl

这个回收过程很简单,直接将需要回收的节点加入到pool中链表头部就行了。


这个源代码中还有一些其他的数据结构和函数,这里先不分析了,因为还不太清楚或者猜测其用途,等真正遇到了再回头添加。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值