nginx一些重要结构体及其操作接口详解

 1. ngx_str_t

        在nginx源码目录的src/core下面的ngx_string.h|c里面,包含了字符串的封装以及字符串相关操作的api。nginx提供了一个带长度的字符串结构ngx_str_t,它的原型如下:

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

         在结构体当中,data指向字符串数据的第一个字符,字符串的结束用长度来表示,而不是由’\0’来表示结束。所以,在写nginx代码时,处理字符串的方法跟我们平时使用有很大的不一样,但要时刻记住,字符串不以’\0’结束,尽量使用nginx提供的字符串操作的api来操作字符串。

1.1 nginx提供的的操作字符串相关的api

  • #define ngx_string(str)     { sizeof(str) - 1, (u_char *) str }

        ngx_string(str)是一个宏,它通过一个以’\0’结尾的普通字符串str构造一个nginx的字符串,鉴于其中采用sizeof操作符计算字符串长度,因此参数必须是一个常量字符串。

  • #define ngx_null_string     { 0, NULL }

        定义变量时,使用ngx_null_string初始化字符串为空字符串,符串的长度为0,data为NULL。

  • #define ngx_str_set(str, text)                                            \ (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text

        ngx_str_set用于设置字符串str为text,由于使用sizeof计算长度,故text必须为常量字符串。

  • #define ngx_str_null(str)   (str)->len = 0; (str)->data = NULL

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

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

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

  • 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);

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

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

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

2. ngx_poll_t

        对于nginx处理的每个http request, nginx会生成一个ngx_pool_t对象与这个http request关联,所有处理过程中需要申请的资源都从这个ngx_pool_t对象中获取,当这个http request处理完成以后,所有在处理过程中申请的资源,都将随着这个关联的ngx_pool_t对象的销毁而释放。

ngx_pool_t相关结构及操作被定义在文件src/core/ngx_palloc.h|c中。       

typedef struct ngx_pool_s        ngx_pool_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 nginx提供的的操作pool相关的api

  • ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);

        创建一个初始节点大小为size的pool,log为后续在该pool上进行操作时输出日志的对象。 需要说明的是size的选择,size的大小必须小于等于NGX_MAX_ALLOC_FROM_POOL,且必须大于sizeof(ngx_pool_t)。

        选择大于NGX_MAX_ALLOC_FROM_POOL的值会造成浪费,因为大于该限制的空间不会被用到(只是说在第一个由ngx_pool_t对象管理的内存块上的内存,后续的分配如果第一个内存块上的空闲部分已用完,会再分配的)。

        选择小于sizeof(ngx_pool_t)的值会造成程序崩溃。由于初始大小的内存块中要用一部分来存储ngx_pool_t这个信息本身。

        当一个ngx_pool_t对象被创建以后,该对象的max字段被赋值为size-sizeof(ngx_pool_t)和NGX_MAX_ALLOC_FROM_POOL这两者中比较小的。后续的从这个pool中分配的内存块,在第一块内存使用完成以后,如果要继续分配的话,就需要继续从操作系统申请内存。当内存的大小小于等于max字段的时候,则分配新的内存块,链接在d这个字段(实际上是d.next字段)管理的一条链表上。当要分配的内存块是比max大的,那么从系统中申请的内存是被挂接在large字段管理的一条链表上。我们暂且把这个称之为大块内存链和小块内存链。

  • 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_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);

        按照指定对齐大小alignment来申请一块大小为size的内存。此处获取的内存不管大小都将被置于大内存块链中管理。

  • ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);

        对于被置于大块内存链,也就是被large字段管理的一列内存中的某块进行释放。该函数的实现是顺序遍历large管理的大块内存链表。所以效率比较低下。如果在这个链表中找到了这块内存,则释放,并返回NGX_OK。否则返回NGX_DECLINED。

        由于这个操作效率比较低下,除非必要,也就是说这块内存非常大,确应及时释放,否则一般不需要调用。反正内存在这个pool被销毁的时候,总归会都释放掉的嘛!

  • ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);

        ngx_pool_t中的cleanup字段管理着一个特殊的链表,该链表的每一项都记录着一个特殊的需要释放的资源。对于这个链表中每个节点所包含的资源如何去释放,是自说明的。这也就提供了非常大的灵活性。意味着,ngx_pool_t不仅仅可以管理内存,通过这个机制,也可以管理任何需要释放的资源,例如,关闭文件,或者删除文件等等。下面我们看一下这个链表每个节点的类型:

typedef struct ngx_pool_cleanup_s  ngx_pool_cleanup_t;
typedef void (*ngx_pool_cleanup_pt)(void *data);

struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;
    void                 *data;
    ngx_pool_cleanup_t   *next;
};

data:      指明了该节点所对应的资源。

handler: 是一个函数指针,指向一个可以释放data所对应资源的函数。该函数只有一个参数,就是data。

next:      指向该链表中下一个元素。

  •  void ngx_destroy_pool(ngx_pool_t *pool);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值