linux铁三角之内存(一)

  • 作者: 雪山肥鱼
  • 时间:20210312 06:18
  • 目的:深入理解内存
# 铁三角总览
  ## 分页机制
    ### 内存和内存空间是两回事
    ### MMU功能简介
    ### PTE低12位的作用
      #### rwx权限
      #### kernal/kernal+user 权限
      #### CPU 熔断
  ## 物理内存分 zone
    ### zone_dma 说明
  ## 内存管理的buddy 算法
  ## CMA 工作机制

铁三角总览

铁三角的关系.png

内存的问题是linux中最难的问题之一。CPU铁三角:

  • CPU 调度:调度器调度算法
  • I/O:比较独立
    • I/O还没有学习,但是I/O要透过CPU MEM内存去看,不能孤立的去看
  • MEM:内存在cpu和I/O肩负了一个中间交换的角色

分页机制

分页机制.png

内存和内存空间是两回事

在一个CPU眼里,在访问外部时有两种可能性即 内存空间与IO空间

  • 内存空间
    凡是通过指针访问的都是内存空间
  • I/O空间
    • I/O空间是x86架构中非常特殊的一块空间,不能用指针直接访问,而是用in out指令 访问外设的寄存器


      x86架构.png

RISK处理器的内存空间
risk处理器的内存空间分为两块

  • 真正的内存
  • 位于内存空间的寄存器
    所以内存空间和内存是两个概念,内存位于内存空间中,但内存空间并不是内存


    RISK架构.png

MMU 功能介绍

MMU与页表.png
  • 为什么每个进程都可以有很大的地址空间,因为他们使用的页表不同,每次切换进程,页表也就切换了
  • CPU 只会发出虚拟地址,MMU会帮助CPU 通过查表的方式进行虚拟地址和物理地址的转换
  • 虚拟地址和物理地址的转换在前面内存系列章节已经有所阐述,这里就不再赘述。
    • 但是还需要注意:Page Table 中的 每一项的PTE的PFN是 这一页物理地址的基地址,VPN 也是 虚拟地址页的基地址(不包括偏移),所以很明显页表存储的是 <VPN, PFN>的对应关系。与整个虚拟地址无关,只与虚拟地址算出的虚拟页地址相关。

常见的错误理解:
指针发出的地址非物理地址,而一定是虚拟地址
物理地址不是个指针,而是个整数!!指针是CPU发出来的,是虚拟地址。cpu不可能通过物理地址访问内存和寄存器,一切都要通过MMU进行翻译

int * p = 1M;// 这个1M是虚拟地址
int  address = 1M; //linux 内核中 对应的物理地址的类型是 u32/u64 int

当然 虚拟地址 还是有可能 等于物理地址,那只是个巧合而已。

PTE 低12 位

rwx权限 读写执行权限 在linux中每一个不同的东西都会有不同的权限

代码段只有r+x,那么尝试去重写代码段,页表中查找代码段相应的地址,但是发现页表中该处并没有写权限
马上MMU会给CPU 发出一个 page fault 的中断。CPU收到后,马上去查,发现有人在写代码段,此时CPU 发出 segmentation fault信号,将程序杀掉。

相关应用举例:缓冲区攻击

缓冲区攻击示意图.png

  • b()函数调用func() 在内存空间中会将b()中返回func()的下一条地址 压栈
  • 假设我在func()通过memcpy认为破坏上面提到的下一条地址,从而让PC指针的下一跳,飞到data段
  • data段可以收到网络过来的数据,我们对其进行修改,注入一段偷窃代码。
  • 但是由于MMU在查看PTE时,data段只有R+W的权限,会引发page fault,linux内核一查,发现有人在修改只有R+W的data段,立刻发出segmentation fault,将程序杀掉

权限代码举例:最简单的尝试修改 const 变量
main.c:

//main.c
#include<stdio.h>
const int a = 2;
extern void add_a(void);

int main(int argc, char ** argv)
{
    add_a();
    return 0;
}

a.c:

extern int a;

void add_a(void)
{
  g++;
}

很显然在执行函数后,程序会报sgmentation fault.

  1. cpu 访问 const int a , 回去查页表
  2. MMU 不仅会查物理地址,还会查看权限
  3. MMU 发现没有写权限,陷入trap: page fault
  4. OS 查看 page fault 原因,有人在违规操作内存
  5. OS 发出 signal 11: SIGSEGV -> 程序挂掉,报segmentation fault

页表中的 kernal/User+kernal 权限 什么空间可以访问

linux区别于实时操作系统的最大区别就是内核是内核,应用时应用,内核空间从中剥离出来的
内核需要提供一个无条件的环境,让应用程序跑在上面,应用程序无论怎么调内核,内核都不能挂掉。

三环结构.png

内核的东西,应用程序时访问不了的,三环的东西,时访问不了零环的。每一个APP 需要用特权指令,才能陷入0环。

CPU 熔断介绍 Meltdown

非常生动的讲解了什么是CPU熔断:
https://blog.csdn.net/qq_27633421/article/details/106213665
理论上用户态的东西是不能访问内核态的,但是CPU熔断的出现彻底颠覆了人们对地址空间的理解。
让人可以拿到内核的数据,理论上不可能从应用态拿到内核态的东西
基本原理如下:

//可能不太合理
a[256] 每一个成员都比较大,超过cache line
//理论上读不出来C
c = *k // k是内核空间的地址 理论上这里就要收到page fault,但是intel的狂奔以及预测
for(int i = 0;i<256,++i)
  开始时间
  a[i]
  结束时间
  delta = 结束 - 开始
Meltdown.png

这些访问时间是不同的,
当执行到a[c]时,因为intel的狂奔+prefechting机制,cache 已经提前缓存了,所以会造成时间差,那么反推出来,我就知道*k 里面存的是c了。
这里的理解貌似也有点问题,举得例子貌似也不太对,原理的话,还是看链接里所举得代码例子吧

李小璐汉堡问题:背景:两个狗仔想知道李小璐在KFC里买了什么
1、李小璐KFC 买了一个汉堡
2、狗仔A 去问 李小璐买什么我就买什么
3、店员拒绝,但是后厨听到了,做了一个汉堡(CPU狂奔+prefeching)
4、狗仔B来问 你们这里最快的是什么,店员问后厨要最快做出来的东西
5、后厨送出来一个汉堡,李小璐买的是汉堡

理解页表中 kernal/kernal+user 的权限管理狠重要。

物理地址不是指针 而是整数

32位系统的虚拟地址空间肯定只有32位,但是32位的物理地址空间是可以远大于32位的,32位处理器的内存条是可以大于4G的,只要页表可以支持64位范围内即可。即32处理器的大地址扩展(arm32位处理器最后一代即支持大于16G的物理内存)。
每个进程的页表地址不相同,多个进程一定会把16G物理地址瓜分掉,这很容易理解

物理内存分zone原理

dma zone 说明

物理内存分区.png

dam zone的存在是因为外设硬件的缺陷,64位处理器,也没有什么High Memory Zone 了。也就是说dam zone 有没有,也是硬件所决定的。当然也可能有 dma_32 zone
3G-4G 开机就线性映射好了,所以用两个宏搞定。其他地址的需要翻译。

CPU MME DMA 外设关系图.png

可以访问内存的有CPU和 DMA(GPU等也划到这里),DMA访问内存是不通过CPU的,直接访问内存。比如网卡收到报文,DMA直接将网络包送到内存中,不需要再通过CPU,这样CPU就空闲下来,DMA最主要的功能就是让CPU有时间去做其他事情。
这样理解的话 DMA并不会让你的外设边的更快。快慢是由总线频率决定的。跟CPU访问还是DMA访问没有半毛钱关系。
有些DMA引擎是有缺陷的,比如x86的isa总线,只能访问16M以下的内存,超过16M根本就访问不到了。申请高于16M也没用,因为DMA根本访问不到
所以Linux的应对方式是将内存砍一刀,砍出一块16M的空间。这时DMA申请的内存带有GFP_DMA,那么OS在低于16M的地方给他申请内存。

这片低于16M内存不只对DMA开放,谁都可以申请,没有任何缺陷的DMA可以访问任意内存,用于DMA内存,并不一定来自DMA总(无缺陷的DMA可以在zone_high申请内存),DMA_ZONE,也不一定用于DMA(低于16M的部分,谁都可以申请)
所以 dam_alloc_coherent申请的内存,并不一定来自于zone_dma,需要考虑外设是否有缺陷,
这个函数第一个参数就是 device结构体,会填写dma的访问范围.如果dam支持访问所有MEM,那么申请的内存可以是任意位置的,并不一定在zone_dma内。
如果没有一个DMA有缺陷,那么其实本质上并不需要ZONE_DMA
举例:

举例.png

内存管理的 Buddy 算法

不可能跨zone申请内存.png

首先要明确:申请一片内存是不可能跨zone的。
Buddy算法将每一个总分成一页一页的slot后。
将1页空闲的放在一个链表上,2页空闲放在链表上,4页放在一张链表上,2^n个页放在一张链表上。然后不停的进行拆分合并。
例如刚开机时,16页空闲内存挂在16页buddy上,此时申请了1页内存,空闲15页,不允许有15页,必须时2^n,那么会被拆成 8 4 2 1 放在各自的buddy链表上。
buddy 算法管理内存的方式:

buddy算法.png

每一个块链表上挂着2^n次方个page. 最大可申请的内存是最后1个 2^10,也就是一次性申请4M内存。
全世界任何正整数都可以分割成2^n次方的和

cat /proc/buddyinfo 就可以显示出来


BuddyInfo.png

但是在buddy算法不停的申请释放的时候,连续内存会很少,内存碎片化问题会导致申请连续内存失败。不停的拆分合并拆分合并,导致内存就散了,碎片化了。

那么引发出来一个经典的问题:谁会申请连续的物理内存。

  • 应用程序?
    错错错! 应用程序申请的内存,都可以通过MMU进行优化。都是虚拟内存,地址空间中的连续,而不是物理内存的连续。
  • DMA 物理连续
    绝大多数DMA是不带MMU的,所以搞不清虚拟地址和物理地址,所以只能给出连续的物理地址给DMA.

解决方案:预留内存,预留了100多M,显示器的给显示器,给GPU的给GPU。
类似当年买电脑的时候,集成显卡,从内存里预留出来一部分给显存,一样的原理。

了解CMA的工作机制 - Contiguous memory allocated

给应用程序分配 movable 页,等到dma来要连续空间的时候,应用程序的page 移走。


CMA工作机制.png

physical address 上的moveable页,就算移走了页关系,只要更新page table 的映射关系就行了。

  1. 应用程序申请了8M的堆空间
  2. DMA外接摄像头,申请32M空间,但此时没有连续的32M空间
  3. 调用 dma_alloc_coherent
  4. linux 满山遍野的寻找 4k大小的内存,凑出来8M
  5. 修改page table 映射关系
  6. 内存就被挤出来了

关于DMA:
CMA 也可以配置多个,分区域管理,避免单个DMA区域的碎片化
留个印象,以后再说

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355