栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux内存管理

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux内存管理

目录

链接

文件系统各组件的关系

处理器查询页表的过程

cache的一致性

内存管理大致流程

内存管理的伙伴系统

线性映射区

释放内存页面

假设不考虑libc的因素,malloc分配100Byte,那么实际上内核是为其分配100Byte吗?

假设使用printf打印指针bufA和bufB指向的地址是一样的,那么在内核中这两块虚拟内存是否“打架”了呢?

缺页中断


链接
  • 链接可以认为是一个目录项,其中除了指向文件名的指针,并不存在其他数据。

  • 目标文件删除时,符号链接仍然继续保存。

  • 对每个符号链接都使用了一个独立的inode。相应inode的数据段包含了一个字符串,给出了链接目标的路径。

文件系统各组件的关系

 

处理器查询页表的过程
  • 处理器根据页表基地址控制寄存器TTBCR和虚拟地址来判断使用哪个页表基地址寄存器,是TTBR0还是TTBR1。页表基地址寄存器中存放着一级页表的 基地址。

  • 处理器根据虚拟地址的bit[31:20]作为索引值,在一级页表中找到页表项,一级页表一共有4096个页表项。

  • 第一级页表的表项中存放有二级页表的物理基地址。处理器根据虛拟地址的bit[19:12]作为索引值,在二级页表中找到相应的页表项,二级页表有256个页表项。

  • 二级页表的页表项里存放有4KB页的物理基地址,因此处理器就完成了页表的查询和翻译工作。

cache的一致性

MESI协议。

总线监听协议依赖于这样的事实,即所有的总线传输事务对于系统内所有的其他单元是可见的,因为总线是一个基于广播通信的介质,因而可以由每个处理器的 cache来进行监听。

内存管理大致流程
  • 当了解物理内存和物理页面时,会接触到struct pg_ data_ t、struct zone和struct page等数据结构,这3个数据结构描述了系统中物理内存的组织架构。struct page数据结构除了描述一个4KB大小(或者其他大小)的物理页面外,还包含很多复杂而有趣的成员。

  • 当了解怎么分配物理页面时,会接触到伙伴系统机制和页面分配器(pageallocator),页面分配器是内存管理中最复杂的代码之一。

  • 有了物理内存,那怎么和虚拟内存建立映射关系呢?在Linux内核中,描述进程的虚拟内存用struct vm_area_struct 数据结构。虚拟内存和物理内存采用建立页表的方法来完成建立映射关系。为什么和进程地址空间建立映射的页面有的叫匿名页面,而有的叫pagecache页面呢?

  • 当了解malloc()怎么分配出物理内存时,会接触到缺页中断,缺页中断也是内存管理中最复杂的代码之一。

  • 这时,虚拟内存和物理内存已经建立了映射关系,这是以页为基础的,可是有时内核需要小于一个页面大小的内存,那么slab机制就诞生了。

  • 上面已经建立起虚拟内存和物理内存的基本框图,但是如果用户持续分配和使用内存导致物理内存不足了怎么办?此时页面回收机制和反向映射机制就应运而生了。

  • 虚拟内存和物理内存的映射关系经常是建立后又被解除了,时间长了,系统物理页面布局变得凌乱不堪,碎片化严重,这时内核如果需要分配大块连续内存就会变得很困难,那么内存规整机制(Memory Compaction)就诞生了。

如果采用页表映射的方式,段映射表就变成一级映射表(在Linux内核中称为PGD),其表项提供的不再是物理段地址,而是二级页表的基地址。32位虚拟地址的高12位(bit[31:20])作为访问一级页表的索引值,找到相应的表项,每个表项指向一个二级页表。以虚拟地址的次8位(bit[19:12])作为访问二级页表的索引值,得到相应的页表项,从这个页表项中找到20位的物理页面地址。最后将这20位物理页面地址和虚拟地址的低12位拼凑在一起,得到最终的32位物理地址。

内存管理的伙伴系统

Linux系统采用伙伴系统解决外部碎片问题,采用slab解决内部碎片的问题。

伙伴系统的宗旨就是用最小的内存块来满足内核对于内存的请求。在最初,只有一个块,也就是整个内存,假如为1M大小,而允许的最小块为64K。那么当我们申请一块200k大小的内存时,就要先将1M的块分裂成两等分,各为512K,这两份之间的关系就称为伙伴,然后再将第一个512K的内存块分裂成两等分,各为256K,将第一个256K的内存块分配给内存,这样就是一个分配的过程。

线性映射区

内核空间只有1GB大小。这1GB的映射空间,其中有一部分用于直接映射物理地址,这个区域称为线性映射区。在ARM32平台上,物理地址[0:760MB]的这一部分内存被线性映射到[3GB:3GB+760MB]的虚拟地址上。

内核通常把物理内存低于760MB的称为线性映射内存,而高于760MB以上的称为高端内存。

vmalloc区域在ARM32内核中,从VMALLOC_START开始到VMALLOC_END结束,即从0xf0000000到0xff000000,大小为240MB。在VMALLOC_START开始之前有一个8MB的洞,用于捕捉越界访问。

 

释放内存页面

释放内存页面的核心功能是把页面添加到伙伴系统中适当的free_area链表中。在释放内存块时,会查询相邻的内存块是否空闲,如果也空闲,那么就会合并成一个大的内存块,放置到高一阶的空闲链表free_area中。如果还能继续合并并邻近的内存块,那么就会继续合并,转移到更高阶的空闲链表中,这个过程会一直重复下去,直至所有可能合并的内存块都已经合并。

假设不考虑libc的因素,malloc分配100Byte,那么实际上内核是为其分配100Byte吗?

假设不考虑libc库的因素,malloc分配100Byte,那么内核会分配多少Byte呢?处理器的MMU硬件单元处理最小单元是页,所以内核分配内存、建立虚拟地址和物理地址映射关系都是以页为单位,PAGE_ALIGN(addr)宏让地址addr按页面大小对齐。

假设使用printf打印指针bufA和bufB指向的地址是一样的,那么在内核中这两块虚拟内存是否“打架”了呢?

使用printf打印两个进程的malloc分配的虛拟地址是-一样的,那么内核中这两个虚拟地址空间会打架吗?其实每个用户进程有自己的一份页表,mm_ struct 数据结构中有一个pgd成员指向这个页表的基地址,在fork新进程时会初始化--份页表。每个进程有一个mm_struct数据结构,包含一个属于进程自己的页表、一个管理VMA的红黑树和链表。进程本身的VMA会挂入属于自己的红黑树和链表,所以即使进程A和进程B。使用malloc分配内存返回的相同的虛拟地址,但其实它们是两个不同的VMA,分别被不同的两套页表来管理。

缺页中断

在malloc()和mmap()两个用户态API函数的内核实现时,我们发现它们只建立了进程地址空间,在用户空间里可以看到虚拟内存,但没有建立虚拟内存和物理内存之间的映射关系。当进程访问这些还没有建立映射关系的虚拟内存时,处理器自动触发一个缺页异常,Linux内核必须处理此异常。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/277173.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号