Linux内存及页面缓存管理概要总结
Linux内存及页面缓存管理概要总结
LastRitter 发表于3个月前
Linux内存及页面缓存管理概要总结
  • 发表于 3个月前
  • 阅读 904
  • 收藏 18
  • 点赞 1
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: Linux内存管理部分的内容很多,这里对其关键部分进行概要总结,对其整体有个基本认识,以便深入各个细节。

物理内存管理

页面内存管理

Linux把物理内存划分为若干个大小相同(通常是4k)的页面,每个页面使用struct page描述,在内核初始化时会根据物理内存大小和页面大小,初始化一个struct page数组mem_map[]对系统中所有的页面进行统一管理。

物理页面描述

使用Node,Zone,Page三级结构进行管理。

  • 对于NUMA计算机,有多个Node,非NUMA计算机则只有一个Node。
  • 每个Node中有3个Zone,分别为DMA,Normal和HighMem(有的还有DMA32等其他Zone,不是必须,有的有特殊用途,此处忽略)。在32位CPU中,DMA为从3G开始的16M地址空间,Normal为接下来的880M地址空间,HighMem为最后的128M地址空间。在64位CPU中,由于目前只用了48位地址,共256T地址空间,内核态占用高128T地址空间,所有物理内存都可以被映射到内核,所以没有HighMem Zone(其实也是有的,只是跟32位的有区别)。
  • Page是内核物理内存管理的最小单位,包含各种该页面内存的状态信息,分配状况等。

物理页面分配

使用Buddy,以2的N次方个页面为单位进行内存分配,主要解决外部碎片问题。

物理页面回收

回收类型

内存中并非所有物理页面都是可以进行回收的,内核占用的页不会被换出,只有与用户空间建立了映射关系的物理页面才会被换出。总的来说,以下这些种物理页面可以被 Linux 操作系统回收:

  • 进程映射所占的页面,包括代码段,数据段,堆栈以及动态分配的“存储堆”( malloc 分配的)。
  • 用户空间中通过 mmap()把文件内容映射到内存所占的页面。
  • 匿名页面(没有映射到文件的都是匿名映射,用户空间的堆和栈):进程用户模式下的堆栈以及是使用 mmap 匿名映射的内存区(共享内存 区)。注:堆栈所占页面一般不被换出。
  • 特殊的用于 slab 分配器的缓存,比如用于缓存文件目录结构 dentry 的 cache,以及用于缓存索引节点 inode 的 cache
  • tmpfs 文件系统使用的页。
回收时机
  • 周期性的检查:这是由后台运行的守护进程 kswapd 完成的。该进程定期检查当前系统的内存使用情况,当发现系统内空闲的物理页面数目少于特定的阈值时,该进程就会发起页面回收的操作。
  • “内存严重不足”事件的触发:在某些情况下,比如,操作系统忽然需要通过伙伴系统为用户进程分配一大块内存,或者需要创建一个很大的缓冲区,而当时系统中 的内存没有办法提供足够多的物理内存以满足这种内存请求,这时候,操作系统就必须尽快进行页面回收操作,以便释放出一些内存空间从而满足上述的内存请求。 这种页面回收方式也被称作“直接页面回收”。

swap内存管理

在低速磁盘上选定一块空间,以页面大小(通常是4k)为单位划分空间(开头还有4k的swap分区描述结构),以页面为单位进行管理。

虚拟内存管理

内核态虚拟内存管理

内核态虚拟内存分配

  • 使用slab分配器(嵌入式系统使用轻量级slub分配器,大型服务器使用支持大量大内存分配的slob分配器),主要解决外部碎片问题。

  • 在此基础上创建一系列的页面缓存,比如task_struct,inode,file缓存。

  • kmalloc使用slab创建一系列以2的N次方大小为单位的页面缓存进行内存分配,所以分配的内存的物理连续的,且地址空间位于Normal Zone。

  • vmalloc与vmalloc使用的分配方法稍有不同,分配的内存可能是屋里不连续的,且映射空间在HighMem Zone。

用户态虚拟内存分配

  • malloc进行内存分配实际上是通过brk和mmap函数实现的,brk和mmap函数仅仅是在进程的task_struc中创建新的vma,以及为进程创建新的页表,并未进行实际内存分配。
  • 实际内存分配发生在当用户初次访问内存引起的缺页中断中,使用buddy分配器以页面为单位进行分配。

页面缓存管理

  • 命名页面,比如所有的文件或者块设备所对应的页面缓冲,也就是有后备存储的缓冲。在Linux的所有文件或者块设备的IO过程中,除了使用DirectIO方式之外,全部会使用内存进行缓冲。如果使用read/write方式,则会有块缓冲,如果使用mmap方式,则会使用页缓冲。在新版的Linux内核中,这二者已经融为一体,使用相同的不同的数据结构描述相同的数据页面,且对于inode相同的文件或块设备,其缓冲在整个内核中只有唯一的一份。

  • 匿名页面,比如用户态分配的内存,无论是brk还是mmap分配,也就是没有后备存储的页面。

  • 在页面回收时,对于命名页面,如果为脏则陷入后备存储后丢弃,对于匿名页面,如果为脏则写入swap存储。

  • 页面缓存回收使用LRU2Q算法,将不常用的页面释放掉。

用户态可以对命名页面进行控制的函数

  • fadvise系列函数,控制缓存页面的加载,丢弃。

  • mlock系列函数,锁定或解锁缓存页面。

  • mincore函数, 查看命名页面状态。

共有 人打赏支持
粉丝 19
博文 29
码字总数 100790
×
LastRitter
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: