Glibc——堆利用机制[拓展]

news2024/12/23 18:01:23

 

目录

1、什么是堆

2、使用动态分配的内存

3、系统调用brk和mmap

3.1 brk()

3.2 mmap()

4、多线程与Arena

5、维护多个堆


1、什么是堆

堆是每个程序被分配到的一块内存区域,和栈的区别主要在于堆内存是动态分配的。也就是说,程序可以从“heap“段请求一块内存,或者释放一块内存。是ELF文件当中的一个段。


另外,堆内存是全局的,即在程序的任意位置都可以访问到堆,并不一定要在调用“malloc”的那个函数里访问。这是因为 C 语言使用指针指向动态分配的内存。但相比访问栈上的静态局部变量,使用指针也带来了一定的开销。

2、使用动态分配的内存

GLibc 采用 ptmalloc2 内存分配器管理堆内存,相比前身的 dlmalloc,它增加了对多线程的支持。

借助 stdlib.h 我们可以使用 malloc 和 free 函数来操作堆内存:

#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>
int main(){
    char* buffer = (char*)malloc(10);
    assert(buffer);
    strcpy(buffer, "hello");
    printf(buffer);
}

malloc函数介绍:

malloc
void* malloc (size_t size);
Allocate memory block
Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.

The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.

If size is zero, the return value depends on the particular library implementation (it may or may not be a null pointer), but the returned pointer shall not be dereferenced.

Parameters
size
Size of the memory block, in bytes.
size_t is an unsigned integral type.

Return Value
On success, a pointer to the memory block allocated by the function.
The type of this pointer is always void*, which can be cast to the desired type of data pointer in order to be dereferenceable.
If the function failed to allocate the requested block of memory, a null pointer is returned.

注意:

向堆区申请空间时,并不是真实的申请所需要的字节空间,而会有标准库进行多申请字节空间,用于记录申请空间的属性信息(申请时间,申请大小,访问权限等信息)(cookie数据),free在释放空间时,便可根据起始位置获取属性信息,得到需要释放空间的大小。

即使是申请0个字节空间,malloc依旧是会分配一个最小的chunk

free函数介绍:

free
void free (void* ptr);
Deallocate memory block
A block of memory previously allocated by a call to malloc, calloc or realloc is deallocated, making it available again for further allocations.

If ptr does not point to a block of memory allocated with the above functions, it causes undefined behavior.

If ptr is a null pointer, the function does nothing.

Notice that this function does not change the value of ptr itself, hence it still points to the same (now invalid) location.

Parameters
ptr
Pointer to a memory block previously allocated with malloc, calloc or realloc.

Return Value
none

注意:

free函数,如果传递的是空指针,将不会进行任何操作,如果传递的之前已经被free过了,再次free就会造成一个double free,其后果是不可预测的。

3、系统调用brk和mmap

注意,申请内存时,Linux内核会先分配一段虚拟内存,真正使用时才会映射到物理内存。

参考文章:进程地址空间

3.1 brk()

brk()通过增加 break location 来获取内存,一开始 heap 段的起点 start_brk 和 heap 段的终点 brk 执行同一位置。

地址空间随机化(Address Space Layout Randomization)(ASLR)是一种操作系统用来抵御缓冲区溢出攻击的内存保护机制。这种技术使得系统上运行的进程的内存地址无法被预测,使得与这些进程有关的漏洞变得更加难以利用。

ASLR 关闭时,两者指向 data/bss 段的末尾,也就是 end_data

ASLR 开启时,两者指向 data/bss 段的末尾加上一段随机 brk 便宜

 注意:

与 ' sbrk() ' 的区别,后者是 C 语言库函数, ’ malloc ‘ 源码中的 ’ MORECORE ‘ 就是调用的 ' sbrk() '。

当一直使用brk()往上移动,可能会导致与其他区域重叠,此时可以使用mmap()

3.2 mmap()

用于创建私有匿名映射段,主要是为了分配一块新的内存,且这块内存只有调用 ' mmap() ' 的进程可以使用,所以称之为私有的,与之进行相反操作的是 ' munmap() ',删除一块内存区域上的映射。

brk相当与你真的拿到了这块内存,而mmap相当于对于不同进程在MemoryMappingSegment创建映射段,并进行了标记。

4、多线程与Arena

前面提到,ptmalloc2的一大改进就在于多线程,那么他是如何做到的呢?不难猜到,每个线程必定要维护一些独立的数据结构,并且对这些数据结构的访问是需要加锁的。的确,在ptmalloc2中,每个线程拥有自己的freelist,也就是维护空闲内存的一个链表;以及自己的arena,一段连续的堆内存区域。特别地,主线程的arena 叫做main_arena,非主线程arena叫做non_main_arena

注意:只有main_arena 可以访问 heap段和mmap 映射区域,non_main_arena只能访问mmap 映射区域。

注:线程较多时,互斥锁机制会导致性能下降。

当我们在程序中第一次申请内存时还没有heap段,因此132KB的heap段,也就是我们的main_arena,会被创建(通过brk()),无论我们申请的内存是多大。对于接T来的内存申请,malloc 都会从 main_arena 中尝试取出一块内存进行分配。如果空间不够,main_arena 可以通过brk()扩张;如果空闲空间太多,也可以缩小。

那么对于non_main_arena 呢?前面提到它只能访问mmap 映射区域,因为在创建时它就是由mmap()创建的—1MB的内存空间会被映射到进程地址空间,不过实际上只有132KB是可读写的,这132KB就是该线程的heap结构,或者叫 non_main_arena。

注:当然了,当申请的空间大于128KB且arena 中没有足够空间时,无论在哪个arena里都只能通过mmap()分配内存。

arena也不是和线程一对一的,实际上有数量限制:

For 32 bit systems:

        Number of arena =2* number of cores.

For 64 bit systems:

        Number of arena =8* number of cores.

        而当我们free一小块内存时,内存也不会直接归还给内核,而是给ptmalloc2让他去维护,后者会将空闲内存丢入bin中,或者说 freelist 中也可以。如果过了一会我们的程序又要申请内存,那么 ptmalloc2 就会从bin 中找一块空闲的内存进行分配,找不到的话才会去问内核要内存。

5、维护多个堆

前面提到, main_arena只有一个堆,并且可以灵活地放缩; non_main_arena则只能通过mmap()获得一个堆。那么如果 non_main_arena 里分配的堆内存不够了怎么办?很简单,再mmap()一次,创建一个新的堆。

所以,在 non_main_arena里,我们必须考虑如何维护多个堆的问题。这里我们会涉及三个头部:

heap_info:每个堆的头部,main_arena 是没有的

malloc_state : arena的头部, main_arena的这个部分是全局变量而不属于堆段

malloc_chunk :每个 chunk 的头部

具体一点,heap_info完整定义如下:

typedef struct _heap_info
{
    mstate ar_ptr; /* Arena for this heap. */ 
    struct _heap_info *prev; /* Previous heap. "/ 
    size_t size; /* Current size in bytes. "/
    size_t mprotect_size; /* Size in bytes that has been mprotected \
                                PROT_READ|PROT_WRITE. */


/* Make sure the following data is properly aligned, \
    particularly that sizeof (heap_info) + 2* SIZE_SZ is a multiple of \
            MALLOC_ALIGNMENT. "/

    char pad[—6 *SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;

而malloc_state的完整定义如下:

/**
 * 全局malloc状态管理
 */
struct malloc_state
{
  /* Serialize access. 同步访问互斥锁 */
  __libc_lock_define (, mutex);
 
  /* Flags (formerly in max_fast).
   * 用于标记当前主分配区的状态
   *  */
  int flags;
 
  /* Set if the fastbin chunks contain recently inserted free blocks.  */
  /* Note this is a bool but not all targets support atomics on booleans.  */
  /* 用于标记是否有fastchunk */
  int have_fastchunks;
 
  /* Fastbins fast bins。
   * fast bins是bins的高速缓冲区,大约有10个定长队列。
   * 当用户释放一块不大于max_fast(默认值64)的chunk(一般小内存)的时候,会默认会被放到fast bins上。
   * */
  mfastbinptr fastbinsY[NFASTBINS];
 
  /* Base of the topmost chunk -- not otherwise kept in a bin */
  /* Top chunk :并不是所有的chunk都会被放到bins上。
   * top chunk相当于分配区的顶部空闲内存,当bins上都不能满足内存分配要求的时候,就会来top chunk上分配。 */
  mchunkptr top;
 
  /* The remainder from the most recent split of a small request */
  mchunkptr last_remainder;
 
  /* Normal bins packed as described above
   * 常规 bins chunk的链表数组
   * 1. unsorted bin:是bins的一个缓冲区。当用户释放的内存大于max_fast或者fast bins合并后的chunk都会进入unsorted bin上
   * 2. small bins和large bins。small bins和large bins是真正用来放置chunk双向链表的。每个bin之间相差8个字节,并且通过上面的这个列表,
   * 可以快速定位到合适大小的空闲chunk。
   * 3. 下标1是unsorted bin,2到63是small bin,64到126是large bin,共126个bin
   * */
  mchunkptr bins[NBINS * 2 - 2];
 
  /* Bitmap of bins
   * 表示bin数组当中某一个下标的bin是否为空,用来在分配的时候加速
   * */
  unsigned int binmap[BINMAPSIZE];
 
  /* 分配区全局链表:分配区链表,主分配区放头部,新加入的分配区放main_arean.next 位置 Linked list */
  struct malloc_state *next;
 
  /* 分配区空闲链表 Linked list for free arenas.  Access to this field is serialized
     by free_list_lock in arena.c.  */
  struct malloc_state *next_free;
 
  /* Number of threads attached to this arena.  0 if the arena is on
     the free list.  Access to this field is serialized by
     free_list_lock in arena.c.  */
  INTERNAL_SIZE_T attached_threads;
 
  /* Memory allocated from the system in this arena.  */
  INTERNAL_SIZE_T system_mem;
  INTERNAL_SIZE_T max_system_mem;
};

ptmalloc的空闲chunk都是通过在malloc_state上的bins数组来管理的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/623431.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LPC1114 - AD采集

一、基础知识 1.1位操作 对寄存器的bit5写0&#xff1a; 寄存器&~&#xff08;1<<5&#xff09;&#xff1b; 现在运用你的C语言知识分析一下&#xff0c;把十进制的1写成二进制32位数就是&#xff1a; 00000000000000000000000000000001 &#xff08;1<<5&…

微服务下如何选择OAuth2授权之四种模式

OAuth2.0是一个授权框架&#xff0c;他规定了客户从授权服务器获取令牌Token的规则。 一、OAuth2的组成部分 1.OAuth2.0需要解决的问题 要理解OAuth2.0&#xff0c;先要知道为什么会有这个东西产生&#xff0c;或者说他能帮我们解决什么问题&#xff0c;其实简单说他就是帮我…

【解决】跨设备访问Ubuntu接口文档,请求超时,ping不通问题

文章目录 一、问题描述二、系统环境三、问题原理说明1. 常见问题原因2. 说说IP 地址和子网掩码不匹配问题 四、有风险的解决方法1. 一般的解决方法&#xff1a;2. 我们的解决方法&#xff1a;第一&#xff1a;第二&#xff1a; 选择网络适配器第三&#xff1a;桥接模式第四&…

js常用的一些技巧【一行】

前言 总结一些常用的&#xff0c;但是一时可能想不起来的一些js小技巧&#xff0c;方便CV 数组 生成数组 当你需要要生成一个0-99的数组 方案1 const createArr (n) > Array.from(new Array(n), (v, i) > i) const arr createArr(100) // 0 - 99 数组方案2 const c…

相同性能和体积的磁体,吸力是一样的吗?

很多小伙伴可能都会有这样一个疑问&#xff0c;相同性能和体积的磁体&#xff0c;它们的吸力一样吗&#xff1f;网上有说钕铁硼磁铁的吸力是自身重量的640倍&#xff0c;这可信吗&#xff1f; 这个问题其实可以发散开&#xff0c;那就是磁铁的吸力与哪些因素有关。首先需要明确…

【已解决】qt4安装包下载含下载链接(完全版)

总所周知&#xff0c;c qt4.8是一个稳定版本&#xff0c;而qt4.8去网上找的我好辛苦&#xff0c;而且官网时而挂机一样&#xff0c;网站崩溃一样&#xff0c;即使找到了&#xff0c;它们也会让你下载qt4.8版本&#xff0c;而那些&#xff0c;比如这里就会显得手足无措。 问题…

爱创科技闪“药”亮相第62届全国制药机械博览会!

2023年5月28日-30日&#xff0c;第62届&#xff08;2023年春季&#xff09;全国制药机械博览会暨2023中国国际制药机械博览会在青岛国际世界博览城完美收官。全国药机展是业界公认的专业化、国际化、规模大、展品全、观众多&#xff0c;集贸易、研讨于一体的制药装备行业交流平…

FPGA实战开发-基于的ddr图像缓存设计(上)

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; 本文主要基于DDR的图像缓存设计 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 先用图像产生模块产生一个1080P60Hz的测试图像&#xff0c;然…

内网程序配置外网访问方案

该方案可解决客户公司没有固定IP&#xff0c;内网IIS程序配置外网访问。如果有固定IP&#xff0c;可以直接在公司主路由器上映射端口即可。 一、申请一个公司域名和云服务器 二、在申请的公司一级域名下&#xff0c;解析一个二级域名&#xff0c;使用泛域名方式&#xff0c;解…

Mysql版本升级教程【5.x到8.x】

目录 0.查看当前版本1.备份导出原数据2.停止Mysql服务3.卸载Mysql相关组件4.删除Mysql安装目录5.删除Mysql数据目录6.官网下载新版安装包7.安装新版Mysql8.配置环境变量 0.查看当前版本 1.备份导出原数据 可以在Navicat里将相关数据库存到.sql文件中&#xff0c;到时候直接导入…

阿里面试太为难我了,阿里面试了7轮(拿下P7岗offer)

前言 今年的大环境非常差&#xff0c;互联网企业裁员的现象比往年更严重了&#xff0c;可今年刚好是我的第一个“五年计划”截止的时间点&#xff0c;说什么也不能够耽搁了&#xff0c;所以早早准备的跳槽也在疫情好转之后开始进行了。但是&#xff0c;不得不说&#xff0c;这…

准备跳槽的兄弟可以看看...

八股文为什么这么火爆&#xff1f; 因为只要大家技术和能力过关&#xff0c;八股文能帮助大家在面试时有很好的表现和稳定的发挥&#xff0c;让面试官预估到你能带来的价值&#xff0c;从而实现薪资高涨幅。 总结了一些小伙伴的面试经验&#xff0c;和我自己多年的资料库存&a…

Zabbix“专家坐诊”第194期问答汇总

问题一 Q&#xff1a;请问一下&#xff0c;我这个监控上了光交和V7000通过trap&#xff0c;mib文件也上传了&#xff0c;usr/snmp/mibs/V7000目录&#xff0c;是创建的监控项调用此文件夹下的mib文件&#xff0c;还是自动找呢&#xff1f; A&#xff1a;mib文件只用于mib内容…

深度学习架构-Tensorflow

深度学习基本概念 人工智能是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能的目的 就是让计算机能够像人一样思考。 强人工智能&#xff1a;就是要使机器学习人的理解、学习和执行任务的能力。 弱人工智能&#xff1a;指用…

计算机网络安全的主要内容是什么?CISP题库分享

在技术上&#xff0c;网络安全包括物理安全、运行安全、信息安全和安全保证四个方面: 物理安全 包括环境安全、设备安全和记录介质安全。环境安全涉及中心机房和通信线路的安全保护问题&#xff1b;设备安全涉及设备的防盗和防毁、设备的安全使用等问题&#xff1b;记录介质安…

linux-docker备份数据库

利用计划任务和批处理从docker容器中备份数据库文件到宿主机指定目录 如何创建定时任务 创建计划任务&#xff08;定时任务&#xff09;&#xff1a; crontab -e打开后是VI编辑器&#xff0c;将自己计划任务的内容写到里边然后wq&#xff08;保存并退出&#xff09;就行了 查…

当涉及到嵌入式开发时

以下是一些建议和关键要点&#xff0c;可以帮助您进行有效的开发&#xff1a; 硬件选择&#xff1a;根据项目需求选择合适的硬件平台和组件&#xff0c;包括处理器、存储器、传感器和通信接口等。考虑功耗、性能、可靠性和成本等因素。 软件开发环境&#xff1a;选择适合嵌入式…

3.1 增加多进程执行playwright

增加了多进程的方式执行测试代码&#xff0c;对代码改动比较大 1、case case目录依然是自动生成 2、config dir_collection.py新增了配置 mkdir_collections [case,log,img, ] del_collections [results,report ] del_regex temp3、data/img/log/resource/video data/im…

Linux内核4.14版本——drm框架分析(6)——实例注册drm device/ encoder/crtc/plane/connector等

目录 1. 简介 2. drm device的注册 3. fops 根据前面几篇文档的介绍&#xff0c;我们知道了drm的整体的构成&#xff0c;后面的文章我们从实际的一个例子中进行分析。 1. 简介 kernel版本&#xff1a;4.14 gpu&#xff1a;ARM Mali DP650 hdmi&#xff1a;dw hdmi 涉及的…

[已解决]无法在Windows 11中扩展C盘

如果你的台式电脑或笔记本电脑刚刚升级到Windows 11&#xff0c;如果你没有足够的硬盘空间来保存新文件和软件&#xff0c;那你可能会收到磁盘空间不足的警告。在这种情况下&#xff0c;你可能需要扩展分区来解决这个问题。 虽然Windows系统自带了“磁盘管理”工具&a…