Linux虚拟内存相关知识

梦想与她 提交于 2020-03-07 14:15:36

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内存池管理中会引入内部碎片,外部碎片,内存利用率也低。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!