Linux内存管理

Linux内存管理

物理内存

三个级别

  1. Page 大小为4k,内存的基本单位
  2. Zone 管理Page的队列
    1. ZONE_DMA 内核专用,存放DMA(直接存储器访问)读取IO设备的数据
    2. ZONE_NORMAL 内核专用,存放内核的相关数据
    3. ZONE_HIGHMEM 高端内存 用户进程存放数据
  3. Node节点 一个CPU对应一个Node

内存分配

  • 大内存 利用伙伴系统分配

    将ZONE中的page分组,组装为链表,链表存放页块的集合

  • **小内存 **slub分配

    将几个页单独拎出来作为缓存,里面维护了链表,每次在链表中获取对应的内存,用完后不清空

内存映射

内存映射:将虚拟内存地址映射到物理内存地址,为了完成内存映射,内核为每个进程维护了一张页表(存储在CPU的内存管理单元MMU中),记录虚拟地址与物理地址的映射关系。

linux给每个进程提供一个独立的虚拟地址空间,并且是连续的,进程就可以方便的访问内存(虚拟内存)

虚拟地址空间=[内核空间+用户空间]

32位系统:[用户空间3G(0x0-0xc0000000)+内核空间1G(0xfffffff-0xc0000000)]3:1

64位系统:[用户空间128T(0x0-0x00007FFFFFFFF000)+未定义空间+内核空间128T(0xFFFF900000000000-0xFFFFFFFFFFFFFFFF)]

用户态:Text(代码)+Data(数据),BSS(全局变量)+堆+栈+mmap内存映射区的的内存虚拟地址范围

内核态:

  • 直接映射区 逻辑地址-offset=物理地址,映射到ZONE_DMA和ZONE_NORMAL

  • 动态映射区

    所有的内存分配都由内核程序分配,用户无权限 ,所以内核空间需要映射到所有物理内存地址

    采用直接映射,1G只能映射1G

    动态映射:内核空间的逻辑值映射到物理内存中的ZONE_HIGHMEM的任何一个地址,使用完之后再映射其他物理内存

    1. 动态内存映射 使用完后映射其他物理内存
    2. 永久内存映射 一个地址只能只能映射一个物理地址
    3. 固定内存映射 被特定的函数调用引用地址

    区别:

    • 直接映射的规则是定义好的,一个逻辑读地址对应的物理地址是固定的
    • 动态映射是动态绑定的,通过页表查询

只有实际使用的虚拟地址才会分配内存 128+128

内存调用,只有在首次访问才会分配,此时进程访问的虚拟地址在MMU存储的页表中查询不到,系统产生缺页异常,进入内核空间分配物理内存,更新进程页表,再返回用户空间,恢复进程的运行

页表

MMU规定的内存映射最小单位(4KB)

  • 多级页表(64位)

    内存分成区块管理,映射关系->区块索引和区块内的偏移

    linux五级页表[全局页目录(PGD)+上层页目录(PUD)+中间页目录(PMD)+直接页表(PTE)+页(Offset)]

  • 大页

    比普通页更大的内存块,常用在大量内存的进程上

虚拟内存空间分布

[0x0-只读段+数据段+堆+文件映射+栈-0xC0000000](用户态)+内核空间[0xc0000000-0xFFFFFFFF](内核态)

堆和文件映射是动态分配的(malloc函数)

内存回收

  • 回收缓存(LRU算法-回收最近最少使用的内存页面)

  • 回收不常访问的内存,通过交换分区写到磁盘中

    交换分区(swap分区,虚拟内存):把一块磁盘分区当成内存,暂时不用的数据放到磁盘,使用时从磁盘取到内存中

  • 杀死进程(OOM-out of memory)

    监控内存使用情况,通过oom_score为每个进程内存使用情况打分,可以手动设置oom_adj,调整oom_score

内存工具

free 查看内存使用情况

top 查看进程内存使用情况(排序)

Buffer Cache

  • buffers (对磁盘数据的缓存)对原始磁盘块的临时存储,缓存磁盘数据,把分散的写入集中起来,统一优化磁盘的写入,将多次小的写入合并为大的写入
  • Cached (对磁盘文件的缓存)读文件的页缓存,缓存从文件读取的数据,下次访问直接从内存中返回

普通进程只能看到内存提供的虚拟内存

进程通过malloc申请内存后,不会立即分配,在首次访问时才通过缺页异常分配

TLB

缓存虚拟地址和物理地址的对应关系,查询物理地址的时候先查TLB,找不到再查页表

虚拟空间和物理内存都分为内核空间和用户空间

虚拟地址需要通过页表转为物理地址才能使用

用户虚拟空间只能映射物理内存中的用户内存,无法映射内核内存,用户进程只能操作用户内存

内核空间只能被内核使用

用户进程调用系统调用的时候,对应的代码和数据保存在内核空间中

调用内核空间读取文件的时候,首先会拷贝到内存空间,再将数据从内核空间拷贝到用户空间,用户进程不能访问内核空间。

posted @ 2022-04-14 15:00  流光之中  阅读(221)  评论(0编辑  收藏  举报