内存

2019-08-29  本文已影响0人  Virtualer
1. 内核空间和用户空间

在32位的系统下,内存拥有4G(2^32)的寻址能力。大多数操作系统会将4G空间中的一部分给内核使用,应用程序无法直接访问,这块内存称为内核内存空间。

剩余空间按称为用户内存空间。

2. 内存区域
3. 实现方式

操作系统是通过内存管理器实现内存的申请和划分的,并且负责将虚拟内存地址和物理内存地址映射起来。映射方式是内部的结构体存储指向空间地址。

4. malloc的实现

将内存的处理交给内核去做无疑是可行的,但是系统中存在着无数程序的无数申请和释放内存操作,内核调用的性能消耗是很大的,进而影响应用程序性能。
比较好的做法是程序向操作系统申请空间,由程序自己的运行库去管理,当此处空间被使用完,再根据需要向操作系统申请。

5. Linux的堆管理

Linux下堆分配方式有两种系统调用,bk()和mmap(),分配的都是虚拟内存空间。标准C语言库中的malloc/free进行申请和释放内存,底层都是由brk/mmap/munmap实现的。

  • brk():设置进程数据段的结束地址,可以扩大或者缩小数据段(linux系统中的数据段和BSS段统称数据段)。如果将数据段的结束地址向高地址位移动,那么扩大的部分就可以供程序使用,然后将这部分作为堆使用。
  • mmap():向操作系统申请一块虚拟内存空间,此空间位于文件映射区,就是堆和栈中间。linux中的glibc的malloc是小于128k的空间在现有堆中分配出来,大于128k的空间调用mmap函数分配一块匿名空间,在匿名空间中分配空间。
6. 最大malloc(linux)

最大申请空间受到诸多因素干扰,比如系统限制或者物理内存和交换空间总和等。mmap申请匿名空间时系统会为它在内存或交换空间中预留下地址,但是不能超过空闲内存和空闲交换空间的总和。

7. 堆分配算法
  • malloc
    将堆中各个空闲块根据链表链接。申请空间时遍历查找合适大小,拆分出来;释放空间时则合并进链表中。最后链表存在很多细碎空间,在申请一块大内存时候malloc会请求延时,以便整理细碎空间,合并成一块大内存。
  • 位图
    将堆划分为大量相等的块。申请空间时,分配整倍数的块大小,第一个块称为head,其余称为body,我们可以使用一个整数数组记录块的使用情况。每个块均只有头、主体和空闲三种状态,那么只需要两位就可以表示出来所有块的状态,所以称为位图。
  • 对象池
    将堆空间划分为大小相等的块(与位图类似),它认为某种情况下每次分配的空间都相等,所以每次返回一个块的大小,可以变化为链表或者位图。因为不用每次查找合适的大小内存,所以效率很高。

实际上,堆的分配算法是多种算法复合而成的,并不是单一的算法。

上一篇 下一篇

猜你喜欢

热点阅读