首页 > 代码库 > Linux虚拟内存相关知识
Linux虚拟内存相关知识
Linux 的虚拟内存管理有几个关键概念:
1、每个进程都有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址;
2、虚拟地址可通过每个进程上的页表(在每个进程的内核虚拟地址空间)与物理地址进行映射,获得真正物理地址;
3、如果虚拟地址对应物理地址不在物理内存中,则产生缺页中断,真正分配物理地址,同时更新进程的页表;如果此时物理内存已耗尽,则根据内存替换算法淘汰部分页面至物理磁盘中。
Linux 虚拟地址空间如何分布?
Linux 使用虚拟地址空间,大大增加了进程的寻址空间,
虚拟地址空间内由低地址到高地址分别为:
1、只读段:该部分空间只能读,不可写;(包括:代码段、rodata 段(C常量字符串和#define定义的常量) )
2、数据段:保存全局变量、静态变量的空间;
3、堆 :就是平时所说的动态内存, malloc/new 大部分都来源于此。其中堆顶的位置可通过函数 brk 和 sbrk 进行动态调整。
4、文件映射区域:如动态库、共享内存等映射物理空间的内存,一般是 mmap 函数所分配的虚拟地址空间。
5、栈:用于维护函数调用的上下文空间,一般为 8M ,可通过 ulimit –s 查看。
6、内核虚拟空间:用户代码不可见的内存区域,由内核管理(页表就存放在内核虚拟空间)。
32 位系统有4G 的地址空间::
其中 0x08048000~0xbfffffff 是用户空间,0xc0000000~0xffffffff 是内核空间,包括内核代码和数据、与进程相关的数据结构(如页表、内核栈)等。另外,%esp 执行栈顶,往低地址方向变化;brk/sbrk 函数控制堆顶_edata往高地址方向变化。
64位系统结果怎样呢? 64 位系统是否拥有 2^64 的地址空间吗?
事实上, 64 位系统的虚拟地址空间划分发生了改变:
1、地址空间大小不是2^32,也不是2^64,
这可通过#cat /proc/cpuinfo 来查看:
cache_alignment : 64
address sizes : 39 bits physical, 48 bits virtual
linux glibc malloc 是如何分配,回收内存的:
1、 malloc() 调用时,会冲系统堆上分配吗? 不一定。申请小块内存时,malloc先从自己的内存池中找,如果有的话直接用内存池种的。如果内存池中没有,则先从系统堆中申请(比如 sbrk)一大块128K多放入内存池,然后分配。 申请大块时,直接用mmap分配。
2、free()时,内存一定会归还给系统的堆上吗? 不一定。
关于内存泄漏:
狭义的内存泄漏就是代码中malloc/new分配了内存空间,该释放时却没有free/delete ,这样没有使用到的变量占用了进程的内存空间。
广义的内存泄漏:随着进程的运行,进程占用的内存空间不停增长。 这里使用malloc库,即使malloc,free这里使用正确,还是由可能出现内存泄漏,因为malloc内存池管理中会引入内部碎片,外部碎片,内存利用率也低。
Linux虚拟内存相关知识