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

    1. 介绍

    内存,这里指的是随机存取存储器,即RAM,现在普遍使用的是DDR SDRAM
    内存是CPU能直接寻址的存储空间,用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据

    2. 寻址

    地址空间是指CPU对存储器编码地址的范围,现代CPU地址总线多为32位,因此地址空间可达2的32次方,即4GB

    下图是外设和地址空间的映射关系

    MemoryMap
    从上图中可以看到,各类存储器(高速缓冲存储器、内存、外存、外设等)通过总线与CPU相连,所有的物理存储器被看作一个由若干存储单元组成的逻辑存储器,每个物理存储器在这个逻辑存储器中占有一个地址段,即一段地址空间

    CPU在这段地址空间中读写数据,实际上就是在相对应的物理存储器中读写数据

    对于外设,CPU通过读写设备上的寄存器来管理和使用,外设寄存器也称为"I/O端口"
    I/O端口有两种寻址方式:独立编址和统一编址
    统一编址:外设接口中的IO寄存器(即IO端口)与主存单元一样看待,每个端口占用一个存储单元的地址,将主存的一部分划出来用作IO地址空间,统一编址也称为“I/O内存”方式,外设寄存器位于“内存空间”
    独立编址:也称单独编址,即IO地址与存储地址分开独立编址,I/O端口地址不占用存储空间的地址范围,这样,在系统中就存在了另一种与存储地址无关的IO地址,CPU也必须具有专用与输入输出操作的IO指令(IN、OUT等)和控制逻辑

    x86 CPU对外设的寻址采用的是独立编址,存在I/O空间的概念
    而大多数嵌入式CPU,如ARM、PowerPC等并不提供I/O空间,通过内存地址访问

    Linux为了兼容不同的CPU,于是它采用一种新的方法,将基于I/O映射方式的或内存映射方式的I/O端口通称为I/O区域

    更多内容参考<Linux中的IO端口映射和IO内存映射>

    3. MMU

    3.1 介绍

    现代处理器中通常包含的MMU(Memory Management Unit,内存管理单元)和Cache(缓存)来协助处理器进行存储空间的访问,从而满足现代操作系统多任务的需求。
    image
    MMU的作用在于将CPU发出的虚拟地址(VA)翻译成物理地址(PA),即进行地址转换;同时提供硬件机制的内存访问权限检查
    Cache的出现是由于CPU与内存的速度不匹配,为了尽可能的发挥CPU的高速度

    不同处理器实现的MMU和Cache差异较大,比较经典的是x86处理器和RISC系列处理器,两者不同之处在于是否分段

    x86处理器的MMU通常有分段和分页,于是有了三种概念,逻辑地址,线性地址,物理地址
    逻辑地址: 机器语言指令用这种地址指定一个操作数的地址或一条指令的地址;这种寻址方式把程序分为若干段,每个逻辑地址都由一个段和偏移量组成。
    线性地址: 线性地址是一个32位的无符号整数,可以寻址2^32(4GB)的地址;其取值范围为0x00000000~0xFFFFFFFF
    物理地址: 内存单元的实际地址,用于芯片级内存单元寻址;物理地址也由32位无符号整数表示

    RISC系列处理器与x86处理器不同,对分段的支持并不好,一般只存在分页的概念

    操作系统对页表的使用
    1. 操作系统在初始化或分配、释放内存时会执行一些指令在物理内存中填写页表,然后用指令设置MMU,告诉MMU页表在物理内存中的什么位置。
    2. 设置好之后,CPU每次执行访问内存的指令都会自动引发MMU做查表和地址转换操作,地址转换操作由硬件自动完成,不需要用指令控制MMU去做。

    3.2 NUMA

    通常认为计算机内存是一种均匀、共享的资源,在忽略硬件高速缓存作用的情况下,期望CPU对内存单元的访问都需要相同的时间,即统一内存架构(Unified Memory Architecture,简称UMA);然而,在一些体系结构(MIPS等)和SMP中,UMA并不成立,于是引入NUMA

    NUMA,Non Uniform Memory Access Achitecture,即非一致性内存访问;在这种模型中,给定CPU对不同内存单元访问的时间可能不一样,系统的物理内存被划分为几个节点(Node);在一个单独的node中,任一给定CPU访问内存单元所需的时间都是相同的;但是对不同的CPU,这个时间可能不同

    更多NUMA内容,参考<Linux的NUMA技术>

    3.3 分页机制

    MMU的存在使得对内存管理的方式多种多样,在操作系统的课程中,有分区式管理、页式管理、段式管理和段页式管理等方式,现代操作系统在实现时多采用分段和分页的机制,Linux在为了简化对内存的管理,同时兼容不同处理器架构,采用分页机制来实现内存管理

    有的CPU采用二级页表结构(如MIPS与x86),但有些CPU采用三级,甚至四级结构。
    Linux为了兼容这些CPU,采用四级页表结构:

     - PGD: Page Global Directory 页全局目录, 是顶级页表
    - PUD: Page Upper Directory 页上级目录, 是第二级页表
    - PMD: Page Middle Derectory 页中间目录, 是第三级页表
    - PTE: Page Table Entry 页表, 最后一级页表; 指向物理页面

    mm_manager

    4. 内存模型

    Linux内核支持三种内存模型

     - Flat Memory 平坦内存模式,这是最常见的模式
    - Discontiguous Memory 非接触式内存模式, 为了支持NUMA
    - Sparse Memory 稀疏内存模式, 主要用来支持内存热插拔

    Linux内核在管理内存时将物理内存从逻辑上划分为节点(Node),内存管理区(Zone),页框(Frame Page)三级结构;物理内存先被划分为Node,每个Node关联一个CPU,各个Node又被划分几个Zone,在一个Zone中则是页框
    dfdf 

    5. 数据结构

    内存管理相关的数据结构包括pg_data_t、zone、page

    pg_data_t的主要数据结构

    作用
    node_zones 保存该节点所拥有的管理区描述符, DMA、NORMAL、HIGHMEM
    node_zonelists 内存管理区的分配策略, 当调用free_area_init_core()时,由build_zonelists()函数设置
    nr_zones node中的zone的数量, 1到3个之间
    node_mem_map node中的第一个page
    bdata 仅用于boot 的内存分配
    node_start_pfn pfn是page frame number的缩写, 用于表示node中的开始那个page在物理内存中的位置的
    node_present_pages node中的真正可以使用的page数量
    node_spanned_pages node中所有存在的Page的数量, 包括可用的、mem_map所占用的及dma所占用的区域
    node_id node的NODE ID, 从0开始
    kswapd_wait node的等待队列

    zone的主要数据结构

    作用
    lowmem_reserve 保留的低地址区域的内存
    pageset page管理的数据结构对象, 内部有一个page的列表(list)来管理. 每个CPU维护一个
    list 用于避免自旋锁的冲突, 其大小和NR_CPUS有关, 编译时确定
    lock 对zone并发访问的保护的自旋锁
    free_area 页面使用状态的信息, 以每个bit标识对应的page是否可以分配
    pages_scanned 上次回收page后, 扫描过的page的数量
    wait_table 等待一个page释放的等待队列哈希表. 会被wait_on_page(),unlock_page()函数使用
    wait_table_hash_nr_entries 哈希表中的等待队列的数量
    zone_pgdat 指向这个zone所在的pglist_data对象
    zone_start_pfn 同node_start_pfn, 用于表示zone中的开始那个page在物理内存中的位置
    present_pages 和node中的类似的成员含义一样
    spanned_pages 和node中的类似的成员含义一样

    page的主要数据结构

    作用
    flags 状态的标志信息, 有大量宏用于设置清楚、检测flag成员中的各个位所表示的状态信息
    _count 访问计数. 当为0说明page是空闲的, 大于0说明一个或多个进程使用或者kernel用于在等待I/O
    index 根据page的使用的目的有2种可能的含义。第一种情况:如果page是file mapping的一部分,它指明在文件中的偏移。如果page是交换缓存,则它指明在address_space所声明的对象:swapper_space(交换地址空间)中的偏移。第二种情况:如果这个page是一个特殊的进程将要释放的一个page块,则这是一个将要释放的page块的序列值,这个值在__free_page_ok()函数中设置
    mapping 当文件或设备需要内存映射,文件或设备的inode对象有一个address_space类型的成员。如果page属于这个文件或设备,mapping将指向inode中这个成员。如果page不属于任何文件或设备,但是 mapping被设置了,则mapping指向了一个address_space类型的swapper_space对象,则page用于管理交换地址空间(swap address space)了
    lru page交换调度策略使用。page可能被调度到active_list或者inactive_list队列里。就是使用lru这个list_head
    private 保存了一些和mapping(文件mapping到内存)有关的一些特定的信息。如果page是一个buffer page,则它就保存了一个指向buffer_head的指针
    virtual 不再用于将high memory的映射到ZONE_NORMAL区域的作用了,除了一些其他的体系结构会用到外

    6. 进程内存管理

    内存管理中MMU的存在使得进程之间相互隔离,进程访问的空间均为虚拟地址空间
    Linux中用struct mm_struct来描述一个进程的虚拟地址空间,也通常称为内存描述符
    每个进程只有一个mm_struct结构,但可能有多个虚拟内存区间(struct vm_area_struct),通常用vma表示,不同vma代表着进程空间的各个区域,比如堆、栈、代码区、数据区、各种映射区等等

    mm 

    参考:
    <Linux内存模型>
    <专栏:Linux内存管理>
    <内存管理的那些事儿>

  • 相关阅读:
    数据库简介
    计算机网络OSI七层协议
    信息论知识点(绪论)
    Wireshark抓取HTTP数据包
    配置FileZilla FTP服务器
    Redis集群搭建的几种方式
    Redis单个分片高可用&哨兵集群
    Redis哈希一致性&对应API操作
    MapReduce实现好友推荐
    window下使用IDEA远程调试伪分布式hadoop集群
  • 原文地址:https://www.cnblogs.com/hzl6255/p/2840042.html
Copyright © 2011-2022 走看看