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_zonesnode中的zone的数量, 1到3个之间
node_mem_mapnode中的第一个page
bdata仅用于boot 的内存分配
node_start_pfnpfn是page frame number的缩写, 用于表示node中的开始那个page在物理内存中的位置的
node_present_pagesnode中的真正可以使用的page数量
node_spanned_pagesnode中所有存在的Page的数量, 包括可用的、mem_map所占用的及dma所占用的区域
node_idnode的NODE ID, 从0开始
kswapd_waitnode的等待队列

zone的主要数据结构

作用
lowmem_reserve保留的低地址区域的内存
pagesetpage管理的数据结构对象, 内部有一个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)了
lrupage交换调度策略使用。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内存管理>
<内存管理的那些事儿>

转载于:https://www.cnblogs.com/hzl6255/archive/2012/12/30/2840042.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值