Linux 内存管理
1 页的概念
linux 内核中把物理页作为内存分配的最小单位,32位CPU 页的大小通常为4K,64位的CPU通常支持8K的也。内存管理单元MMU 同样以页为大小分配内存。
2 内核虚拟地址分区和物理内存分区
在32位内核中,内核虚拟地址空间为0-4G,其中用户态为1-3G空间,内核态为3G-4G,内核空间根据物理地址的特性大概可以分为三个区:
区 | 描述 | 32位系统物理内存大小 |
---|---|---|
ZONE_DMA | 和硬件操作相关的内存区域 | < 16M |
ZONE_NORMAL | 内核正常映射的物理页 | 16 - 896M |
ZONE_HIGH | 高端内存,由于内核空间大小的原理部分页不能永久的映射到内核,需要动态映射的 | > 896M |
下面的图描述了内核地址空间和物理内存的映射关系:
程序在内存中的地址==图片来源于网络==
6.2 sbrk 系统调用 和 “program break" (程序间断点)
程序间断点在最开始指向堆区的起始位置,同时也是数据段的结尾。 malloc 分配内存后,指向分配的内存开始的位置。
linux 系统上malloc 的实现基于sbrk 系统调用。
p1 = sbrk(0); //sbrk(0)返回当前的程序间断点 p = sbrk(1) //将堆区的大小加1,但是返回的是p1的位置
参考
如何实现一个malloc内存的页映射
malloc 调用后,只是分配了内存的逻辑地址,在内核的mm_struct 链表中插入vm_area_struct结构体,没有分配实际的内存。当分配的区域写入数据是,引发页中断,建立物理页和逻辑地址的映射。下图表示了这个过程。
物理页的分配过程在Android 上通过procrank 查看 Vss 和 Rss, Rss 总是小于Vss 就是这个原因。
generic_x86_64:/ # procrank PID Vss Rss Pss Uss cmdline 1509 1077592K 117132K 66232K 57296K system_server 1237 901952K 66596K 56300K 52884K zygote 1623 1061168K 98892K 50847K 44164K com.android.systemui 1236 916248K 78992K 29529K 20532K zygote64 1780 1020240K 63484K 20138K 15684K com.android.phone 2004 1014992K 66748K 20112K 14748K com.android.launcher3
字段 含义 VSS Virtual Set Size 虚拟耗用内存(包含共享库占用的内存) RSS Resident Set Size 实际使用物理内存(包含共享库占用的内存) PSS Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存) USS Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存) 一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
参考:
How the Kernel Manages Your Memory部分内容来源于网络,没有一一注明
网友评论