02Nginx源码分析之总结内存开辟的相关函数(ngx_alloc.c,ngx_palloc.c)

2023-11-12

02Nginx源码分析之总结内存开辟的相关函数(ngx_alloc.c,ngx_palloc.c)

前言:
写这一篇的目的是为了方便接下来的阅读,否则每次都要对应查找相应的函数,非常麻烦。

并且注意:
下面所说的内存对齐,实际上是通过倍数来对齐的,例如按照256对齐,此时只是将返回的首地址变成256的倍数,若想对齐,必须调用ngx_memalign时的参1也传256,这样就可以对齐,即0-256-512,第一次获取内存返回首地址是0(不需要关心开辟的大小),那么第二次开辟内存按照256对齐后,它下次返回的首地址必然是256,所以这样就对齐了。但是如果你第二次对齐的倍数不是256,而是4,8,16,32这些,那么就有可能造成不对齐的情况。

这就是本篇所说的内存对齐,这个内存对齐相对于对齐宏ngx_align来说,更强调对齐首地址。而后者是将整个对齐倍数(即若对齐为16,开辟大小为9,那么调用对齐宏实际占用16的大小)进行对齐,需要区别下一篇所说的内存对齐。

1 首先说ngx_alloc.c源文件中的开辟函数
1)ngx_alloc函数
作用:单独调用malloc开辟内存。

/*
 * 功能:调用malloc开辟内存
*/
void *
ngx_alloc(size_t size, ngx_log_t *log)
{
    void  *p;

    p = malloc(size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "malloc(%uz) failed", size);
    }

    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);

    return p;
}

2)ngx_calloc函数
和上面其实一样,只不过多了一步清零工作。

/*
 * 功能:调用ngx_alloc开辟内存并进行清零操作
*/
void *
ngx_calloc(size_t size, ngx_log_t *log)
{
    void  *p;

    p = ngx_alloc(size, log);

    if (p) {
        ngx_memzero(p, size);
    }

    return p;
}

3)ngx_memalign函数
实际和上面也是一样的,也是开辟内存,只不过多了内存对齐的工作。所以要想内存对齐则调用此函数,否则调用上面的函数即可。

/*
 * 功能:根据宏定义取相应函数,但是功能实现都是一样的。
 * posix_memalign和memalign都是开辟一个size大小的内存空间,并且返回的值与alignment成倍数即内存对齐。它与另一个宏函数ngx_align_ptr是ngx使大内存内存对齐的关键
*/


#if (NGX_HAVE_POSIX_MEMALIGN)

void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;
    int    err;

    err = posix_memalign(&p, alignment, size);//开辟一个内存块,并且传出的p的首地址与alignment成倍数关系即内存对齐

    if (err) {
        ngx_log_error(NGX_LOG_EMERG, log, err,
                      "posix_memalign(%uz, %uz) failed", alignment, size);
        p = NULL;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "posix_memalign: %p:%uz @%uz", p, size, alignment);

    return p;
}

#elif (NGX_HAVE_MEMALIGN)

void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;

    p = memalign(alignment, size);//开辟一个内存块,并且返回的p的首地址与alignment成倍数关系即内存对齐,与上面区别是一个是传出一个是返回值返回
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "memalign(%uz, %uz) failed", alignment, size);
    }

    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "memalign: %p:%uz @%uz", p, size, alignment);

    return p;
}

2 ngx_alloc.c源文件中的开辟函数
1)ngx_palloc函数和ngx_pnalloc函数
这两个函数是最重要的。
但这里只是简单说一下ngx_palloc和ngx_pnalloc,具体里面的ngx_palloc_small和ngx_palloc_large可以到下一篇内存池的文章中理解。
理清ngx_palloc和ngx_pnalloc:实际上这两个函数是一样的,只不过ngx_palloc穿1会进行内存对齐,后者穿0不对齐。所以单独讲ngx_palloc即可。

ngx_palloc:
1)若开辟的内存小于等于内存池的max,则调用小内存开辟,否则调用大内存开辟。
2)开辟小内存ngx_palloc_small的逻辑:在内存池的链表中查找是否有可用的内存,没有则调用ngx_palloc_block开辟新的内存池中给samll,此时内存必定在内存池链表上。
3)开辟大内存ngx_palloc_large的逻辑:调用ngx_alloc开辟一块大内存,交给对应的large结构体管理然后返回。实际上每次开辟大内存他会对前三个管理结构体判断其中的alloc是否为空,若为空则交给前三个管理,否则跳出交给新创建的large结构体管理,此时内存必定在大内存块链表上。

上面的这几句话总结对后面的内存对齐的这几个函数理解非常有用。

void *
ngx_palloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 1);
    }
#endif

    return ngx_palloc_large(pool, size);
}


//ngx_pnalloc同理。
void *
ngx_pnalloc(ngx_pool_t *pool, size_t size)
{
#if !(NGX_DEBUG_PALLOC)
    if (size <= pool->max) {
        return ngx_palloc_small(pool, size, 0);
    }
#endif

    return ngx_palloc_large(pool, size);
}

2)ngx_pcalloc函数
调用上面的ngx_palloc,c代表callback。

/*
 * 重新说一篇ngx_palloc()的作用:调用ngx_palloc_small或者ngx_palloc_large申请一片内存返回。申请的内存在内存池或者大数据块上。
 * 它的作用和ngx_palloc可以是一样的,只不过多了一步清零操作。
*/
void *
ngx_pcalloc(ngx_pool_t *pool, size_t size)
{
    void *p;

    p = ngx_palloc(pool, size);
    if (p) {
        ngx_memzero(p, size);
    }

    return p;
}

3)ngx_pmemalign函数
注意函数名多了个p对比最上面的ngx_alloc.c源文件,这个函数比较少被调用,所以只需要了解一下即可。

/*
 * 它的作用和ngx_palloc_large可以是基本一样的,有两个不同点:
 * 1)调用内存对齐的函数ngx_memalign创建内存,而非像ngx_palloc_large内调用不内存对齐的ngx_alloc。
 * 2)不再去检查前面三个大内存是否为空,而是直接将新创建的大内存p按照头插法放进大内存链表管理。
*/
void *
ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
{
    void              *p;
    ngx_pool_large_t  *large;

	// 1)创建一个内存对齐的大内存
    p = ngx_memalign(alignment, size, pool->log);
    if (p == NULL) {
        return NULL;
    }

	// 2)创建管理大内存的结构体,并在下面赋值进行管理该内存
    large = ngx_palloc_small(pool, sizeof(ngx_pool_large_t), 1);
    if (large == NULL) {
        ngx_free(p);
        return NULL;
    }

	//头插法插进大内存链表
    large->alloc = p;
    large->next = pool->large;
    pool->large = large;

    return p;
}

3 总结
看懂上面后,以后只需瞄一眼这里就可,非常方便。

1)ngx_alloc函数
作用:单独调用malloc开辟内存。
2)ngx_calloc函数
调用ngx_alloc增加清零操作。可认为与ngx_alloc一样。
3)ngx_memalign函数
开辟内存并内存对齐。

4)ngx_palloc函数和ngx_pnalloc函数
这两个函数调用small和large开辟内存。
1)ngx_palloc_samll首先在已有内存池中查找可用内存,没有则调用block开辟新内存,并给新内存池管理再插入到内存池链表,所以调用这两个函数的内存在内存池链表上。但实际并不连续,只是内存池结构体连续。所以调用samll必定在内存池链表。
2)而ngx_palloc_large是调用ngx_alloc直接开辟内存后交给ngx_pool_large_t结构体管理,再插入大内存块链表。所以该函数开辟的内存不在内存池。而是必定在大内存块链表中。
所以:开辟的内存在内存池链表或者在大内存块链表。

5)ngx_pcalloc函数
调用ngx_palloc,增加清零操作。可认为与ngx_palloc一样。

额外函数(较少使用)6)ngx_pmemalign函数
调用ngx_memalign开辟内存对齐的空间,然后交给ngx_pool_large_t结构体管理,再插入大内存块链表。
所以可认为与ngx_palloc_large一样,只不过ngx_palloc_large少了内存对齐但多了检查前三个结构的步骤。

所以可以总结:
1)前三个都是开辟无任何关系管理的内存。
2)后三个需要进行区分:
1:ngx_palloc和ngx_pnalloc开辟的内存在内存池链表或者在大内存块链表。
2ngx_palloc_samll(即block)开辟的内存必定在内存池结构体链表上管理。
3:ngx_palloc_large和ngx_pmemalign开辟的内存必定在大内存块结构体的链表上管理。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

02Nginx源码分析之总结内存开辟的相关函数(ngx_alloc.c,ngx_palloc.c) 的相关文章

随机推荐

  • vs code终端修改字体大小以及其它样式

    1 在文件 gt 首选项 gt 设置 2 用户 gt 工作台 gt 找到settings json点击进入 3 在 settings json文件里添加需要修改的样式 terminal integrated cursorBlinking t
  • 软件资源下载链接

    1 Dreamweaver DW cs5 链接 https pan baidu com s 1kVqqpqJ 密码 9hc4 DW cc2014 链接 https pan baidu com s 1skQvBCL 密码 3kd8 DW cc
  • 数据库系统——复习总结

    数据库系统
  • cvCanny检测边缘,连通重要的非连通区域

    这个函数就是使用canny边缘检测算子检测图象的边缘 在opencv下使用这个函数之前最好将图象平滑处理一下 要不然可能检测不到边缘 检测到的边缘 这些边缘大多还不是连通区域 可以通过3 3的模板将一些相近的边缘连接起来 也可以用cvDil
  • Tesseract-OCR的配置和应用

    1 百度搜索Tesseract OCR下载 Tesseract orc setup 3 02 02 exe 要记得自己的安装目录 博主的安装路径为 C Program Files x86 Tesseract OCR 等会配置环境变量要用 如
  • C# Selenium chromedriver 隐藏Devtool控制台窗口

    爬取网页信息时 使用了C Selenium WebDriver dll chromedriver Chrome 除了chromedriver控制台窗口 可以通过CDS HideCommandPromptWindow true隐藏 还有出现一
  • Health Kit基于数据提供专业方案,改善用户睡眠质量

    什么是CBT I 中国社科院等机构今年发布的 中国睡眠研究报告2023 内容显示 2022年 受访者的每晚平均睡眠时长为7 40小时 近半数受访者的每晚平均睡眠时长不足8小时 47 55 16 79 的受访者的每晚平均睡眠时长不足7小时 这
  • C++异常处理机制(超级详细)

    目录 0 异常处理机制简介 1 传统错误处理机制 通过函数返回值 2 异常处理机制语法 3 异常接口声明 4 异常类型和声明周期 4 1throw基本类型异常 int float char 4 2throw字符串类型异常 4 3throw类
  • 数据可视化(学会用matplotlib绘图)

    1 绘制简单的折线图 import matplotlib pyplot as plt squres 1 4 9 16 25 plt plot squres 把列表传给plot 这个函数尝试根据这些数字绘制出有意义的图形 plt show 打
  • 【取模软件PCtoLCD2002使用教程】

    1 打开取模软件PCtoLCD 2 左上角模式选择为字符模式 3 点击选项 4 设置如下 然后点击确定 5 以16x16汉字取模为例 字宽字高都改为16 然后在输入栏输入汉字 点击生成字模生成的字模如下 然后将字模复制到例程lcdfont
  • 距离向量算法_RIP协议及距离向量算法(上)【44】

    1 RIP协议 RIP 全称Routing Information Protocol 即路由信息协议 RIP是一种分布式的基于距离向量的路由选择协议 是因特网的协议标准 最大优点的简单 RIP协议要求网络中每一个路由器都维护从它自己到其它每
  • Centos 安装mysql8(YUM方式)

    1 执行安装命令 root localhost wget https dev mysql com get mysql80 community release el8 4 noarch rpm root localhost yum modul
  • JAVA 定义静态map并赋值

    private static final Map
  • C语言入门经典三,c语言入门经典第4版和第3版有什么区别

    问 微软的C语言和其他C语言有什么区别吗 答 不知道楼主说的是所谓 微软的c 是指什么概念 个人意见 仅供参考 1 如果是指微软推出的c语言的编译器ms c的话 其实就是c语言各个编译器之间的区别 如果你想深入了解 最好是学习下c标准的制定
  • 【ICS大作业】

    零 摘要 本文对给定的hello程序的生命周期进行了系统性分析 程序经预处理生成hello i 编译生成hello s 汇编生成hello o 最后链接成可执行目标文件hello Shell收到 hello的指令 调用fork函数创建进程
  • 再临SpringBoot——WebFlux处理流程

    文章目录 WebFlux初次尝试 处理过程源码分析 SpringMvc通常是Servlet应用 因此 可能被当前线程阻塞 以远程调用为例 由于阻塞的缘故 导致Servlet容器使用较大的线程池处理请求 而Spring WebFlux通常是非
  • 第一篇——开始

    第一篇 开始 个人简介 学习经历 学习过程 后记 个人简介 个人简介 以山河作礼 学习经历 作为一名本科大一的软件工程专业学生 我已经在CSDN学习了近一年的时间 同时也深入学习了C语言半年 在我的CSDN博客上 我将记录下我在学习过程中的
  • Vue3.0监听props方法

    学习vue3 0记录下props监听 第一种直接监听这个props export default defineComponent props isOpen Boolean emits close modal null setup props
  • 算术表达式的前缀式、中缀式、后缀式相互转换

    中缀表达式 中缀记法 中缀表达式是一种通用的算术或逻辑公式表示方法 操作符以中缀形式处于操作数的中间 中缀表达式是人们常用的算术表示方法 虽然人的大脑很容易理解与分析中缀表达式 但对计算机来说中缀表达式却是很复杂的 因此计算表达式的值时 通
  • 02Nginx源码分析之总结内存开辟的相关函数(ngx_alloc.c,ngx_palloc.c)

    02Nginx源码分析之总结内存开辟的相关函数 ngx alloc c ngx palloc c 前言 写这一篇的目的是为了方便接下来的阅读 否则每次都要对应查找相应的函数 非常麻烦 并且注意 下面所说的内存对齐 实际上是通过倍数来对齐的