指针的本质--u_char*指针在Nginx源码中的应用及原因

GNU下的void *p++相当于char *p++ 也就是移动一个字节。

下面的代码是Nginx中内存池的结构体代码,其中last和end是表示内存地址的。

last是u_char*指针类型也就是unsigned char

typedef struct {
    u_char               *last;
    u_char               *end;
    ngx_pool_t           *next;
    ngx_uint_t            failed;
} ngx_pool_data_t;

 

指针的本质--u_char*指针在Nginx源码中的应用及原因_第1张图片

由于unsigned char*指针表示一个字节 所以是0-255之间

257已经需要2个字节10000001,所以如果用unsigned char*类型来声明该段地址(&k),那么多出的部分会被舍去,所以如果对其解引用就是00000001,而不是257

指针的本质--u_char*指针在Nginx源码中的应用及原因_第2张图片

本来,指针变量不管是什么类型其实都完整的存储了“地址”但是不同类型解引用就会产生对应的值

nginx移动last指针,分配内存的函数

void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    ngx_pool_t  *p;

    if (size <= pool->max) {

        p = pool->current;

        do {
            m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);

            if ((size_t) (p->d.end - m) >= size) {
                p->d.last = m + size;

                return m;
            }

            p = p->d.next;

        } while (p);

        return ngx_palloc_block(pool, size);
    }

    return ngx_palloc_large(pool, size);
}
声明了一个u_char*m的变量,然后返回给空指针。其实,声明last为空指针也可以,那样要如这里: 指针的本质-void和void*指针在nginx中的应用

感觉自己2篇文章其实还是在说指针,讲同一个东西。


如果需要增加内存

static void *
ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
    u_char      *m;
    size_t       psize;
    ngx_pool_t  *p, *new, *current;

    psize = (size_t) (pool->d.end - (u_char *) pool);

    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
    if (m == NULL) {
        return NULL;
    }

    new = (ngx_pool_t *) m;

    new->d.end = m + psize;
    new->d.next = NULL;
    new->d.failed = 0;

    m += sizeof(ngx_pool_data_t);
    m = ngx_align_ptr(m, NGX_ALIGNMENT);
    new->d.last = m + size;

    current = pool->current;

    for (p = current; p->d.next; p = p->d.next) {
        if (p->d.failed++ > 4) {
            current = p->d.next;
        }
    }

    p->d.next = new;

    pool->current = current ? current : new;

    return m;
}
先是声明一个u_char      *m; 后面给其分配内存。

然后是讲*m转化为ngx_pool_t   *new= (ngx_pool_t *) m;

然后把new串到p上,p也就是前面已经分配了的内存池(由于空间不够需要扩容)

最后,返回m。最关键就是m  注意:m和new后来就完全不一样了,因为m是last指针,也就是新分配的内存地址

对于调用ngx_palloc()函数的变量来说,由于ngx_palloc()返回的是void*指针,所以可以给任意其他类型指针!


总结:

因为u_char*和char*指针都是指向1个字节的地址,所以用u_char*和char*指针进行位移运算是非常方便的这也是为什么nginx用u_char*做last指针类型的原因

设想如果用的是Int*,那么last+1实际上就是+4个字节,非常不方便

其实用void*也可以定义last指针的,但是这样需要做一次转换在运算的时候!


所谓内存池就是划一块内存,从内存池中申请就是返回一个地址,和malloc一样本质都是返回一个地址,准确的说是void*


指针的本质--u_char*指针在Nginx源码中的应用及原因_第3张图片

你可能感兴趣的:(指针的本质--u_char*指针在Nginx源码中的应用及原因)