zoukankan      html  css  js  c++  java
  • Linux内存管理

    基础概念关系


    在计算机架构中,硬件主板上主体分为南北桥,北桥主要是CPU内存显卡等之间的数据传输,而南桥主要负责的是IO相关的、外部存储设备、BIOS相关的数据。

    而我们所知的内存管理,实际是程序的逻辑地址,通过分段机制转为线性地址,通过分页机制转为物理地址(这一部由CPU的MMU模块支持),物理地址再通过北桥访问到具体的RAM设备,或者是ISA设备,或者PCI等IO相关(再通过南桥)。

    内存寻址的工作是由Linux内核和MMU共同完成的,其中Linux内核负责cr3,gdtr等寄存器的设置,页表的维护,页面的管理,MMU则进行具体的映射工作。

    另外,学过汇编语言我们知道最原始的访问物理地址是通过CS:IP的分段机制来访问的, 所以x86架构由于历史原因是是分段机制,但是Linux的内存管理是分页机制。为了向前兼容我们把整个内存段落拓宽为只有一段,段基址为0,段限长为4G,只是在段类型和段访问权限上有所区分,并且Linux内核和所有进程共享1个GDT,不使用LDT(即系统中所有的段描述符都保存在同一个GDT中),这是为了应付CPU的分段机制所能做的最少工作。 

    具体线性地址和物理地址转换可以参考如图

    物理地址空间


    0-16M ZONE_DMA,该区域的物理页面专门供I/O设备的DMA使用。之所以需要单独管理DMA的物理页面,是因为DMA使用物理地址访问内存,不经过MMU,并且需要连续的缓冲区,所以为了能够提供物理上连续的缓冲区,必须从物理地址空间专门划分一段区域用于DMA。
    16M-896M

    ZONE_NORMAL,该区域的物理页面是内核直接映射,即内核空间的常用的数据如kernel代码、GDT、IDT、PGD、mem_map数组等放在ZONE_NORMAL里,为的是内核该虚拟地址与物理地址是直接映射,不通过页机制。

    896M-4G ZONE_HEIGHT,该区域是物理高端地址,映射到用户空间和内核部分空间。
    640k-1M 这段地址空间被BIOS和VGA适配器所占据。RAM地址空洞。
    MMIO

    在MMIO中,IO设备和内存共享同一个地址总线,它们的地址空间是相同的; 而在PMIO中,IO设备和内存的地址空间是隔离的。简单点说就是MMIO将IO地址编入内存地址中,调用相应的内存地址即调用到相应的IO设备,而至于往下的是像Inter的int/out指令端口独立编址还是ARM的统一编址则不管。

    虚拟地址空间


    虚拟地址空间 实际意义
    0-3G 用户空间
    3G-4G 内核空间
    3G-3G+16M 对应的物理地址中的ZONE_DMA
    3G+16M-3G+896M 对应的物理地址中的ZONE_NORMAL
    VMALLOC_START-VMALLOCEND vmalloc area
     PKMAP_BASE 持久化内核映射区
     FIXADDR_BASE 临时内核映射区

    内核空间


    对于虚拟地址空间,我们知道0-3G是用户空间,而3G-4G是内核空间,前896M已经用于直接映射了,那么剩下的128M空间需要映射其他的不同位置物理空间,即高端物理空间。

    Kernel提供了三种机制,分别是vmalloc area,持久化内核映射区,临时内核映射区。

    • vmallo area,提供连续的虚拟地址,但是指向的物理地址不一定连续
    • 持久化内核映射区,方便通过物理地址找到对应的虚拟地址,用于固定的线性地址常量,例如0xffffc000,且该常量在编译阶段就可以确定。创建持久内核映射的函数kmap()可能会阻塞当前进程,因此不能用在中断上下文中。
    • 临时内核映射区,与持久内核映射相比,它更快,而且不会阻塞当前进程,因此可以用在中断上下文中。不过,它也有一个弱点,就是使用它的代码不能睡眠。因为每一个CPU都有独自的13个临时映射地址如果切换进程可能导致该地址被改变。

    用户空间 


      

     

    用户进程的代码区一般从虚拟地址空间的0x08048000开始,这是为了便于检查空指针。代码区之上便是数据区,未初始化数据区,堆区,栈区,以及参数、全局环境变量。

    参考:

    Linux内存寻址和内存管理 //进程

    内存管理 //进程

    Linux内存管理

    linux内核之内存管理图解 //进程

    Kernel那些事儿之内存管理(11) --- 内核映射 

    浅谈内存映射I/O(MMIO)与端口映射I/O(PMIO)的区别

  • 相关阅读:
    第63天python学习异常
    第62天python 学习TCP三次握手四次挥手详解
    文件操作
    内置函数
    函数递归
    函数补充
    函数
    购物车程序作业
    集合内置函数
    字典三级菜单
  • 原文地址:https://www.cnblogs.com/GrimReaper/p/9499311.html
Copyright © 2011-2022 走看看