Nginx 基本数据结构

概述

在学习 Nginx 之前首先了解其基本的数据结构是非常重要的,这是入门必须了解的一个步骤。本节只是简单介绍了 Nginx 对基本数据的一种封装,包括 基本整型数据类型、字符串数据类型、缓冲区类型以及 chain 数据类型。

基本数据类型

整型数据

/* 基本数据结构 */

/* Nginx 简单数据类型 */
/* 在文件 src/core/ngx_config.h 定义了基本的数据映射 */

typedef intptr_t        ngx_int_t;
typedef uintptr_t       ngx_uint_t;
typedef intptr_t        ngx_flag_t;
/* 其中 intptr_t uintptr_t 定义在文件 /usr/include/stdint.h 文件中*/

/* Types for `void *' pointers.  */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int		intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned long int	uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int			intptr_t;
#  define __intptr_t_defined
# endif
typedef unsigned int		uintptr_t;

/* 因此,Nginx 的简单数据类型的操作和整型或指针类型类似 */

字符串类型

/* Nginx 字符串数据类型 */
/* Nginx 字符串类型是对 C 语言字符串类型的简单封装,
 * 其定义在 core/ngx_string.h 或 core/ngx_string.c 中
 * 定义了 ngx_str_t, ngx_keyval_t, ngx_variable_value_t
 */

/* ngx_str_t 在 u_char 的基础上增加了字符串长度的信息,即len变量 */
typedef struct {
    size_t      len;    /* 字符串的长度 */
    u_char     *data;   /* 指向字符串的第一个字符 */
} ngx_str_t;

typedef struct {
    ngx_str_t   key;
    ngx_str_t   value;
} ngx_keyval_t;

typedef struct {
    unsigned    len:28;

    unsigned    valid:1;
    unsigned    no_cacheable:1;
    unsigned    not_found:1;
    unsigned    escape:1;

    u_char     *data;
} ngx_variable_value_t;
/* Nginx 字符串的初始化使用 ngx_string 或 ngx_null_string ,这两个宏定义如下 */

#define ngx_string(str) {sizeof(str)-1, (u_char *) str}
#define ngx_null_string {0, NULL}

/* 若已经定义了 Nginx 字符串变量之后再赋值,则必须使用 ngx_str_set, ngx_str_null 宏定义*/

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

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

/* 例如:*/
/* 正确写法*/
ngx_str_t str1 = ngx_string("hello nginx");
ngx_str_t str2 = ngx_null_string;

/* 错误写法*/
ngx_str_t str1, str2;
str1 = ngx_string("hello nginx");   /* 编译出错 */
str2 = ngx_null_string;             /* 编译出错 */

/* 正确写法*/
ngx_str_t str1, str2;
ngx_str_set(&str1, "hello nginx");
ngx_str_null(&str2);
/* 注意:ngx_string 和 ngx_str_set 字符串参数必须是常量字符串,不能是变量字符串 */

内存池类型

内存池类型即是 ngx_pool_t ,有关内存池的讲解可参考前文《Nginx 内存池管理

/* 内存池结构 */
/* 文件 core/ngx_palloc.h */
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_chain_t 结构 */
    ngx_pool_large_t     *large;/* 大块内存链表,即分配空间超过 max 的内存 */
    ngx_pool_cleanup_t   *cleanup;/* 析构函数,释放内存池 */
    ngx_log_t            *log;/* 内存分配相关的日志信息 */
};
/* 文件 core/ngx_core.h */
typedef struct ngx_pool_s   ngx_pool_t;
typedef struct ngx_chain_s  ngx_chain_t;

缓冲区数据类型

缓冲区 ngx_buf_t 的定义如下:

/* 缓冲区结构 */
typedef void *            ngx_buf_tag_t;

typedef struct ngx_buf_s  ngx_buf_t;

struct ngx_buf_s {
    u_char          *pos;   /* 缓冲区数据在内存的起始位置 */
    u_char          *last;  /* 缓冲区数据在内存的结束位置 */
    /* 这两个参数是处理文件时使用,类似于缓冲区的pos, last */
    off_t            file_pos;
    off_t            file_last;

    /* 由于实际数据可能被包含在多个缓冲区中,则缓冲区的start和end指向
     * 这块内存的开始地址和结束地址,
     * 而pos和last是指向本缓冲区实际包含的数据的开始和结尾
     */
    u_char          *start;         /* start of buffer */
    u_char          *end;           /* end of buffer */
    ngx_buf_tag_t    tag;
    ngx_file_t      *file;          /* 指向buffer对应的文件对象 */
    /* 当前缓冲区的一个影子缓冲区,即当一个缓冲区复制另一个缓冲区的数据,
     * 就会发生相互指向对方的shadow指针
     */
    ngx_buf_t       *shadow;

    /* 为1时,表示该buf所包含的内容在用户创建的内存块中
     * 可以被filter处理变更
     */
    /* the buf's content could be changed */
    unsigned         temporary:1;

    /* 为1时,表示该buf所包含的内容在内存中,不能被filter处理变更 */
    /*
     * the buf's content is in a memory cache or in a read only memory
     * and must not be changed
     */
    unsigned         memory:1;

    /* 为1时,表示该buf所包含的内容在内存中,
     * 可通过mmap把文件映射到内存中,不能被filter处理变更 */
    /* the buf's content is mmap()ed and must not be changed */
    unsigned         mmap:1;

    /* 可回收,即这些buf可被释放 */
    unsigned         recycled:1;
    unsigned         in_file:1; /* 表示buf所包含的内容在文件中 */
    unsigned         flush:1;   /* 刷新缓冲区 */
    unsigned         sync:1;    /* 同步方式 */
    unsigned         last_buf:1;/* 当前待处理的是最后一块缓冲区 */
    unsigned         last_in_chain:1;/* 在当前的chain里面,该buf是最后一个,但不一定是last_buf */

    unsigned         last_shadow:1;
    unsigned         temp_file:1;

    /* STUB */ int   num;
};

chain 数据类型

ngx_chain_t 数据类型是与缓冲区类型 ngx_buf_t 相关的链表结构,定义如下:

struct ngx_chain_s {
    ngx_buf_t    *buf;  /* 指向当前缓冲区 */
    ngx_chain_t  *next; /* 指向下一个chain,形成chain链表 */
};
typedef struct {

链表图如下:

参考资料:

《深入理解 Nginx 》

Nginx 从入门到精通

Nginx 代码研究

时间: 2024-07-29 12:24:25

Nginx 基本数据结构的相关文章

nginx高级数据结构源码分析(一)-----双向链表

ng_queue_t是Nginx提供的一个顺序容器,它以双向链表的方式将数据组织在一起. 链表作为顺序容器的优势在于,它可以高效的执行插入.删除.合并等操作,在移动链表中的元素时只需要修改指针的指向,因此,它很适合频繁修改容器的场合. 相对于其他顺序容器,它的优势有以下三点: (1)  实现了排序功能,采用额是插入排序,虽然不太适合超大规模数据的排序,但是简单实用. (2)  它非常轻量级,不负责链表元素所占内存的分配.ngx_queue_t只是把这些分配号内存的元素用双向链表链接起来 (3)

Nginx下编写c模块来阻止HTTP代理服务器的访问

在这篇使用Apache来阻止http代理服务器的访问文章里,我们使用了Apache的mod_rewrite来判断访客的http head头,如果看到了有代理的迹象,就阻止它,能否进一步提高效率呢?于是想到了用nginx来提高效率,为了最快,编写了C模块,这样效率会达至最高. 下面简单介绍一下nginx模块的编写: nginx模块分两种,handle和filter.handle是得到输入后,直接控制输出最终结果:而filter是得到输入后,进行变换,传递给下一个filter依次处理,两种模块稍有区

Nginx源码分析:3张图看懂启动及进程工作原理

编者按:高可用架构分享及传播在架构领域具有典型意义的文章,本文由陈科在高可用架构群分享.转载请注明来自高可用架构公众号「ArchNotes」.   导读:很多工程师及架构师都希望了解及掌握高性能服务器开发,阅读优秀源代码是一种有效的方式,nginx 是业界知名的高性能 Web 服务器实现,如何有效的阅读及理解 nginx?本文用图解的方式帮助大家来更好的阅读及理解 nginx 关键环节的实现.   陈科,十年行业从业经验,曾在浙江电信.阿里巴巴.华为.五八同城任开发工程及架构师等职,目前负责河狸

nginx-nginx数据结构

本篇文章主要记录说明使用nginx时,开辟一个简单http模块的时序图,还有nginx中封装的数据结构及其处理函数. 1.如何开发一个充满异步调用,无阻塞的http模块? 首先,我们需要把程序嵌如到nginx中(最终变异处的二进制程序nginx要包含我们的代码). 然后,这个http模块要能介入到处理流程中. 在正式请求处理时,还要可以获取nginx框架定义的数据结构,解析后的用户请求信息 业务执行完毕后,则要考虑发送响应给用户(包括将磁盘中的文件以http包体的形式发送给用户) 我们都是讨论C

Nginx学习笔记——概要

下面是Nginx模块开发的基础知识,后续的Nginx源码学习分享将会不断推出. Nginx配置文件: Nginx模块构成--hello world为例 模块1 模块2 模块3 模块4 模块5 Nginx数据结构 Nginx基本数结构 Nginx高级数据结构

计算机科学精彩帖子收集

inux源码 LXR 源自"the Linux Cross Referencer",中间的"X"形象地代表了"Cross".与 Source Navigator 类似,它也是分析阅读源代码的好工具.不同的是,它将源代码借助浏览器展示出来,文件间的跳转过程成了我熟悉的点击超链接动作. http://lxr.linux.no/   LXR安装过程简介 linux手册 http://linux.die.net/man/ Linux每周新闻 http:/

nginx学习六 高级数据结构之双向链表ngx_queue_t

1 ngx_queue_t简介 ngx_queue_t是nginx提供的一个轻量级的双向链表容器,它不负责存储数据,既不提供数据的内存分配,它只有两个指针负责把数据链入链表,它跟stl提供的queue不同,stl提供的queue帮助用户存储数据,用户只需要相容器里添加数据即可,而ngx_queue_t,用户必须自己提供存储数据的内存,并且必须定义一种数据结构把ngx_queue_t包含在其中,然后利用ngx_queue_t提供的函数来进行相应的操作. 2 ngx_queue_t结构及其操作 2.

【Nginx】基本数据结构

整型的封装 typedef intptr_t ngx_int _t;//有符号整型 typedef uintptr_t ngx_uint_t;//无符号整型 字符串的封装 typedef struct { size_t len; u_char *data; }ngx_str_t; 链表容器的封装 typedef struct ngx_list_part_s ngx_list_part_t; //链表结点 struct ngx_list_part_s { void *elts;//数组的起始地址

nginx学习九 高级数据结构之红黑树ngx_rbtree_t

1红黑树简介 先来看下算法导论对R-B Tree的介绍: 红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black. 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平的. 红黑树,作为一棵二叉查找树,满足二叉查找树的一般性质.下面,来了解下 二叉查找树的一般性质. 二叉查找树 二叉查找树,也称有序二叉树(ordered binary tree),或已排序二叉树(sorted binary tree