Linux内核之内存1: CPU寻址原理和分页管理

1 CPU寻址内存,虚拟地址、物理地址

(1)寻址内存:

CPU访问外设,有两种类型,一个是内存空间,一个是IO空间;

IO空间,X86通过in/out指令访问外设,IO空间只存在X86架构,在RISC架构不存在;

内存空间,CPU通过指针访问所有内存空间,内存空间分为两类,普通内存位于内存空间的寄存器。其他设备的寄存器,比如通过I2C总线访问触摸屏的寄存器,与CPU内存空间无关。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8j7mPiY-1598498114961)(media/50a48e80431ef2346c44e9ee7ad0bd92.jpg)]

(2) MMU原理

对于一个支持MMU的CPU,只要开启MMU,CPU跟程序员视角一致,看到的永远是虚拟地址;

在访问内存空间时,CPU发一个虚拟地址(指针),MMU把虚拟地址映射为物理地址。

其他硬件设备,比如DMA/IVE(硬件模块不带mmu)访问也是物理地址;

(3)虚拟地址和物理地址:

比如在两个不同的进程QQ/WECHAT里,可以分别定义一个变量,虚拟地址相同(都为1G);真正访问的时候,经过MMU映射到实际不同的物理地址。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pNz6GhCf-1598498114965)(media/89a67e50fdd3e5cb6d8f3912d1cfc7ca.jpg)]

每个进程都维护自己的页表,相同的虚拟地址可以映射到不同的物理地址;

当CPU访问0x1234560时,先查询页地址0x1234对应的物理地址(比如1M),560为页内偏移

patch

int *p=1m; //对指针赋值物理地址,是错误的

(4) 物理地址的本质

在Linux 内核,物理地址定义为一个无符号64/32位整数;

32处理器虚拟地址最大4G,物理地址不一定32位,可以大于4G;

物理地址位数可以大于虚拟地址位数;

2.MMU以及RWX权限、kernel和user模式权限

32位处理器,页表有32位,但实际维护页表只用到高20位,低12位用来存放其他信息比如权限

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tJBEqZx-1598498114966)(media/59422b10736fb696db9d3c5aee37e7d5.jpg)]

CPU访问一个地址,不仅要做虚拟/物理地址页表地址查询,还要检查页表权限,出现非法操作时,MMU拦截CPU访问请求,并报page
fault,CPU收到MMUpage
fault中断时,报段错误,发信号11,进程默认信号处理方式是挂掉。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zMl3k0P-1598498114969)(media/442ba2ae3413cf8938acb0ce05ccd754.png)]

找不到物理地址,或者权限不对,发生段错误;

tips:
gdb layout src

meltdown漏洞,利用时间旁路攻击原理,从用户空间获取内核空间数据;

3.MMU作用总结:

(1). 内存隔离:防止应用程序访问不属于自己的空间,隔离应用对其它应用空间、内核空间的访问。因为它们只能访问自己的虚拟空间,每个进程的虚拟空间都是独立的。
(2). 权限管理:不同地址段拥有不同的访问权限,不能越权访问。
(3). 地址映射:将不连续的物理地址映射为连续的虚拟地址,并可以通过swap机制可以获得比实际内存大得多的使用空间。
前两者实现数据安全,第三条为程序提供空间便利。

该部分由网友Aero Learning补充, 感谢。

再补充两点:
1.直接使用物理内存,当即将运行的程序内存不足时,需要选择一个进程整体换出,这导致有大量数据的换出与换入,效率低下;即MMU可以解决内存使用效率问题

2.有效解决碎片化问题;

3.内存的zone: DMA、Normal和HIGHMEM

32位Linux内核空间物理地址映射在3G~4G,分三个区域,
ZONE_DMA(0~16M):DMA内存分配区;
ZONE_NORMAL(16MB~896MB): 普通映射的内存区域;
ZONE_HIGHMEM(896MB~):高端内存区域,其中的页不能永久映射到内核地址空间;内核一般不使用,如果要使用,通过kmap做动态映射;

存在高端内存的原因是,当物理内存大于虚拟内存寻址范围(1G)时,需要做非线性映射,才能在访问所有物理内存空间范围。32系统一般都划分896M以上物理地址为高端内存。

在目前流行的64位CPU中,由于虚拟寻址位数足够,就不存在高端内存概念了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h1kdEpzf-1598498114970)(media/aaec31c0f8b0f0bea017eb64d643ac62.png)]

896M以下,开机直接映射好(通过virt_to_phys/phys_to_virt简单线性映射),896MB以上动态分配,可以被内核和用户空间访问;

对于64位CPU有足够寻址能力,就不存在869MB问题了,64位处理器,一般没有HGIHMEM ZONE;;

对于一个嵌入式设备,内存太小,也不存在 HIGHMEM区域;

DMAzone存在的根本原因是DMA硬件有缺陷,比如一个典型32位系统ISA设备的DMA只有24位寻址能力,也就是只能访问内存的前16M内存,而整个系统的最大物理内存寻址甚至可以大于1G,超过内核的虚拟空间;

DMA没有MMU,所以只能访问连续物理内存;少数最新的DMA具有MMU,也可以访问物理不连续的内存,MMU页表映射即可。

当为一个DMA有缺陷设备申请内存时,传入标记GFP_DMA,在DMA
ZONE区域分配内存,如果DMA可以访问所有内存空间,则不用受限于DMA_ZONE。而其他普通设备,也可以申请DMA_ZONE.

申请DMA内存,会填入设备访问范围,根据范围确定申请的内存区域;

DMA内存不一定来自于DMA ZONE,DMA ZONE也不一定用于DMA

如果系统所有DMA都没有缺陷,则不存在dma_zone;

DMA直接访问内存,不会让外设访问速度更快,DMA最大好处是解放CPU资源,速度受限外设总线及访问频率;

4.Linux内存管理Buddy算法

Buddy 算法直面物理内存;

Buddy算法把内存中的所有页面按照2的幂次进行分块管理,分配的时候如果没有相应大小块,就把大的块二分成小块;释放的时候,回收的块跟相邻的空闲伙伴块又能合并成大块;

BUDDY页面的分配和使用情况可以通过proc接口/proc/buddyinfo来查看;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PuUxPvYs-1598498114972)(media/502f8458f4c31e1c7b431a9d6adee240.png)]

Buddy有个缺陷,会造成许多内存碎片,比如总和还剩余很大,但是没有足够连续的空余内存可用。

早期采用预留分配方法,给予显卡,摄像头等预留内存,即使设备不使用,也会预留。

5.连续内存分配器(CMA)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3cmxV2YD-1598498114973)(media/f0cc2935990fe273c049ad91edd5fd08.png)]

分配专门的CMA区域,用于DMA设备的内存申请,比如摄像头,

当摄像头设备不用时,该区域可以用于其他内存分配;

当使用摄像头时,将该区域内的所有已申请内存,拷贝到其他分散的页,并且修改对应页表。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h9uvWapO-1598498114974)(media/320ba2181f44e51c8278389a14fdcd07.png)]

这样CMA大块连续内存,就不会被浪费掉,也保持了大块连续内存的访问需求;

把不同的DMA设备,放在不同的CMA,就不会导致内存碎片化;

其他参考文章:

宋宝华《DMA若干误解的彻底澄清》;

内核文档:Doccumentation/devicetree/binding/reserved-memory/reserved-meory.txt

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值