您的位置:首页 > 理论基础 > 数据结构算法

Nginx数据结构及相关接口函数

2013-08-10 09:37 633 查看

Nginx数据结构及相关接口函数

本文转自http://hi.baidu.com/feemood/item/728f8bcd69c0cc3846d5c08f

1. 字符串ngx_str_t

typedef struct {
    size_t      len;
    u_char     *data;
} ngx_str_t;

 

1.1接口函数

ngx_string(str)

初始化一个字符串为str,str必须为常量字符串, 一般只用于声明字符串变量时顺便初始化变量的值。

ngx_null_string

声明变量时,初始化字符串为空字符串,符串的长度为0,data为NULL。

ngx_str_set(str, text)

设置字符串str为text,text必须为常量字符串。

ngx_str_null(str)

设置字符串str为空串,长度为0,data为NULL。

上面这四个函数,使用时一定要小心,ngx_string与ngx_null_string只能用于赋值时初始化,如:

ngx_str_t str = ngx_string("hello world");

ngx_str_t str1 = ngx_null_string();

ngx_str_t str, str1;

ngx_str_set(str, "hello world");

ngx_str_null(str);

不过要注意的是,ngx_string与ngx_str_set在调用时,传进去的字符串一定是常量字符串,否则会得到意想不到的错误。

void ngx_strlow(u_char *dst, u_char *src, size_t n);

将src的前n个字符转换成小写存放在dst字符串当中,调用者需要保证dst指向的空间大于等于n。操作不会对原字符串产生变动。如要更改原字符串,可以:

ngx_str_t str = ngx_string("hello world"); ngx_strlow(str->data, str->data, str->len);

ngx_strncmp(s1, s2, n)

不区分大小写的字符串比较,只比较前n个字符。

ngx_strcmp(s1, s2)

不区分大小写的不带长度的字符串比较。

ngx_int_t ngx_strcasecmp(u_char *s1, u_char *s2);

区分大小写的不带长度的字符串比较。

ngx_int_t ngx_strncasecmp(u_char *s1, u_char *s2, size_t n);

区分大小写的带长度的字符串比较,只比较前n个字符。

u_char * ngx_cdecl ngx_sprintf(u_char *buf, const char *fmt, ...);

u_char * ngx_cdecl ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...);

u_char * ngx_cdecl ngx_slprintf(u_char *buf, u_char *last, const char *fmt, ...);

上面这三个函数用于字符串格式化,ngx_snprintf的第二个参数max指明buf的空间大小,ngx_slprintf则通过last来指明buf空间的大小。推荐使用第二个或第三个函数来格式化字符串,ngx_sprintf函数还是比较危险的,容易产生缓冲区溢出漏洞。

2. 内存池结构ngx_pool_t

typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t;

struct ngx_pool_cleanup_s {

    ngx_pool_cleanup_pt   handler;

    void                 *data;

    ngx_pool_cleanup_t   *next;

};

typedef struct ngx_pool_large_s  ngx_pool_large_t;

struct ngx_pool_large_s {

    ngx_pool_large_t     *next;

    void                 *alloc;

};

typedef struct {

    u_char               *last;

    u_char               *end;

    ngx_pool_t           *next;

    ngx_uint_t            failed;

} ngx_pool_data_t;

struct ngx_pool_s {

    ngx_pool_data_t       d;

    size_t                max;

    ngx_pool_t           *current;

    ngx_chain_t          *chain;

    ngx_pool_large_t     *large;

    ngx_pool_cleanup_t   *cleanup;

    ngx_log_t            *log;

};

 

2.1接口函数

void *ngx_palloc(ngx_pool_t *pool, size_t size);

从这个pool中分配一块为size大小的内存。注意,此函数分配的内存的起始地址按照NGX_ALIGNMENT进行了对齐。对齐操作会提高系统处理的速度,但会造成少量内存的浪费。

void *ngx_pnalloc(ngx_pool_t *pool, size_t size);

从这个pool中分配一块为size大小的内存。但是此函数分配的内存并没有像上面的函数那样进行过对齐。

void *ngx_pcalloc(ngx_pool_t *pool, size_t size);

该函数也是分配size大小的内存,并且对分配的内存块进行了清零。内部实际上是转调用ngx_palloc实现的。

void *ngx_prealloc(ngx_pool_t *pool, void *p, size_t old_size, size_t new_size);

对指针p指向的一块内存再分配。如果p是NULL,则直接分配一块新的new_size大小的内存。

如果p不是NULL, 新分配一块内存,并把旧内存中的内容拷贝至新内存块中,然后释放p的旧内存(具体能不能释放旧的,要视具体的情况而定,这里不再详述)。

3.数组ngx_array_t

typedef struct ngx_array_s       ngx_array_t;
struct ngx_array_s {
    void        *elts;
    ngx_uint_t   nelts;
    size_t       size;
    ngx_uint_t   nalloc;
    ngx_pool_t  *pool;
};

elts:指向实际的数据存储区域。

nelts:数组实际元素个数。

size:数组单个元素的大小,单位是字节。

nalloc:数组的容量。表示该数组在不引发扩容的前提下,可以最多存储的元素的个数。当nelts增长到达nalloc 时,如果再往此数组中存储元素,则会引发数组的扩容。数组的容量将会扩展到原有容量的2倍大小。实际上是分配新的一块内存,新的一块内存的大小是原有内存大小的2倍。原有的数据会被拷贝到新的一块内存中。

pool:该数组用来分配内存的内存池。

3.1接口函数

ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);

创建一个新的数组对象,并返回这个对象。

p:数组分配内存使用的内存池;

n:数组的初始容量大小,即可以在不扩容的情况下最多可以容纳的元素个数。

size:单个元素的大小,单位是字节。

void ngx_array_destroy(ngx_array_t *a);

销毁该数组对象,并释放其对应的内存给对应的内存池。需要注意的是,调用该函数以后,数组对象上个字段的值并没有被清零。所以即便这个时候对象a上各字段还有有意义的值,但是这个对象绝对不应该被再使用了,除非是使用ngx_array_init函数。

void *ngx_array_push(ngx_array_t *a);

在数组a上新追加一个元素,并返回指向新元素的指针。需要把返回的指针使用类型转换,转换为具体的类型,然后再给新元素本身或者是各字段(如果数组的元素是复杂类型)赋值。

void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

在数组a上追加n个元素,并返回指向这些追加元素的首个元素的位置的指针。

static ngx_inline ngx_int_t ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size);

如果一个数组对象是被分配在堆上的,那么当调用ngx_array_destroy销毁以后,如果想再次使用,就可以调用此函数。

如果一个数组对象是被分配在栈上的,那么就需要调用此函数,进行初始化的工作以后,才可以使用。

注意事项: 数组在扩容时,旧的内存不会被释放,会造成内存的浪费。因此,最好能提前规划好数组的容量,在创建或者初始化的时候一次搞定,避免多次扩容,造成内存浪费。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: