• malloc的底层实现


     先看这张图,32位系统,寻址空间是4g,在linux下0-3G是用户模式,3-4G是内核模式。

    在用户模式中有这么几个段(注意内存地址从上到下是,高地址到低地址0xc0000000-0x08048000)

    (1)代码段:储存程序的二进制映像

    (2)数据段:存储已经初始化的全局变量和局部静态变量

    (3)bss段:存储未初始化的全局变量和局部静态变量

    (4)Heap:堆空间,注意节点位置有一个标记brk(),从低地址向高地址扩展

    (5)内存映射:Memory Mapping segment

    (6)stack:栈空间,从高地址向低地址扩展

    Linux维护一个break指针,这个指针指向堆空间的某个地址。从堆起始地址到break之间的地址空间为映射好的,可以供进程访问;而从break往上,是未映射的地址空间,如果访问这段空间则程序会报错。我们用malloc进行内存分配就是从break往上进行的。

    进程所面对的虚拟内存地址空间,只有按页映射到物理内存上,才能真正的使用,由于物理存储容量的限制,整个堆虚拟内存空间不可能全部映射到实际的内存物理。

    获取到break的指针,也就是内存申请的初始指针了。

    系统调用sbrk(位移量)能移动brk指针的位置,同时返回brk指针的位置,来达到申请内存的目的。

    系统调用brk(void* addr),可以直接把brk设置为某个地址,成功返回0,不成功返回1。rlimit限制进程堆内存容量的指针

    从操作系统的角度来说,分配内存有俩种方式,一个是推进brk指针,增加堆的有效区域来申请内存空间,另一种采用mmap,在进程的虚拟地址空间中(堆和栈中间,被称为文件映射区域的地方)找一块空闲的虚拟内存。这俩种都是分配虚拟内存,只有当第一次访问虚拟地址空间时,操作系统才会给分配物理内存。

    malloc是采用brk的方式动态分配内存的。

    malloc函数实质是将可用的内存块连接成一个列表,即空闲链表。当调用malloc函数时,寻找一个可以大到满足用户请求所需要的内存块,然后把该内存块一分为二,一部分用来分配给用户(申请大小),另一部分(如果有的话)

    返回到空闲链表上,如果找不到,就会调用sbrk()推进brk指针来申请内存空间。

    搜索空闲块的算法有:

    (1)首次适配:第一次找到足够大的,就分配。会产生很多的内存碎片

    (2)下一次适配:第二次找到的时候,分配,这样产生的比较少。

    (3)最佳适配:彻底搜索,遍历所有块,找到差值最小的块分配。

    调用free函数,将用户释放的内存块连接到空闲链表上,不进行合并的话, 即使是相邻的内存块还是相当于俩个内存块,形成假碎片,释放内存后,需要将进行内存整理,相邻的小空闲块合并成较大的空闲块。

    内存块的大致结构:meta区+数据区,其中meta区用来记录数据块的元信息(数据区大小,空闲标志位,指针),数据区是真实分配的内存区域,数据区的第一个字节地址就是malloc返回的地址。

    隐式链表和双向链表:

    其中一种是隐式链表,实际上是数组,malloc分配空间必然有一个数据结构,允许它来区分边界,区分已分配和空间的空间,数据结构中包含一个头部信息和有效载荷,有效载荷的首地址就是malloc返回的地址,可能在尾部还有填充,为了保持内存对齐。头部相当于该数据结构的元数据,其中包含了块大小和是否是空闲空间的信息,这样可以根据头地址和块大小的地址推出下一个内存块的地址,这就是隐式链表。
    ————————————————
    还有一种实现方式则是采用显示空闲链表,这个是真正的链表形式。在之前的有效载荷中加入了之前前驱和后驱的指针,也可以称为双向链表。维护空闲链表的的方式第一种是用后进先出(LIFO),将新释放的块放置在链表的开始处。另一种方法是按照地址的顺序来维护。

    如果内存不足,函数未能成功分配储存空间,会返回一个NULL指针,测试返回值是否是NULL。

  • 相关阅读:
    OSPF协议 LSAs
    OSPF协议基础
    交换机Access Trunk Hybrid端口
    网络地址转换 NAT
    访问控制列表 ACL
    路由协议 RIP
    动态路由协议
    static 变量
    Unix网络编程 -- ubuntu下搭建编译环境( 解决unp.h 编译等问题)
    linux 错误处理
  • 原文地址:https://www.cnblogs.com/EvansPudding/p/12602580.html
Copyright © 2020-2023  润新知