内存管理是Linux内核中非常重要的部分,今天和大家一起学习一下。
当我们要学习一个新知识点时,比较好的过程是先理解出现这个技术点的 背景原因,同期其他解决方案,新技术点解决了什么问题以及它存在哪些不足和改进之处,这样整个学习过程是 闭环 的,个人觉得这是个很好的学习思路。
凡事都是相通的,计算机学科的一些问题在现实生活中都可以找到原型,所以我觉得计算机科学家大部分都是善于观察生活并总结归纳的。人类社会就是一台复杂的机器,其中充满了机制和规则,所以有时候跳进代码海洋不如先回到生活之中,寻找原型再探究代码,可能理解会更深刻。
linux内存管理卷帙浩繁,本文只能层层递进地带你领略冰山轮廓,通过本文你将了解到以下内容:
老子的著名观点是无为而治,简单说就是不过多干预而充分依靠自觉就可以有条不紊地运作,理想是美好的,现实是残酷的。
在linux系统中如果以一种原始简单的方式管理内存是存在一些问题的,我们来看几个场景。
2.1 内存管理的问题
假如现在有ABC三个进程运行在linux的内存空间,设定os给进程A分配的地址空间是0-20M 进程B地址空间30-80M,进程C地址空间90-120M,如图:
在某些时候程序空间的访问可能出现问题,比如进程A访问了属于进程B的空间,进程B访问了属于进程C的空间,甚至修改了空间的值,这样就会造成混乱和错误,所以实际中是不允许这种情况发生的。
机器的内存是有限资源,而进程数量是无法确定的,如果在某些时候已经启动的进程占据了所有内存空间,此时就无法启动新进程了,因为没有新内存可分配了,但是我们观察到已经启动的进程有时候是在睡大觉,也就是给了内存也不用,这样效率确实是有点低,所以我们需要一个管理员把不用的内存倒腾出来,另外连续内存实在是很珍贵,很多时候我们没法有效及时地分配连续内存,因此虚拟化和离散化可能会有效提高内存的使用率。
由于程序运行时的位置时不确定的,我们在定位问题、调试代码、编译执行时都会存在很多问题,我们希望每个进程有一致且完整的地址空间,同样的起始位置放置了堆、栈以及代码段等,从而简化编译和执行过程中的 linker 链接器、loader 加载器的使用。
为了解决上述的一些问题,linux系统引入了虚拟空间的概念,虚拟化的出现和硬件有密不可分的联系,可以说是软硬件组合的结果,虚拟地址空间就是在程序和物理空间所增加的中间层,这也是内存管理的重点。
磁盘 disk 作为一种大容量的存储也作为"内存"的一部分参与程序的运行,内存管理系统会将不常用非活跃内存进行页面换出,可以认为内存是磁盘的缓存,内存中保留了活跃的数据,从而间接扩展了有限的物理内存空间,这部分空间称为虚拟内存是相对于物理内存而言的。
本文并不深入地将分段管理内存和分页管理内存,因为将这些细节的优秀文章很多,感兴趣的使用搜索引擎一键即达。
段页机制也不是一蹴而就的,经历了单纯物理分段、单纯分页、单纯逻辑分段等阶段,最终演进出来了分段和分页结合的内存管理方式,段页结合获得了分段和分页的优势也避免了单一模式的弊端,是一种比较好的管理模式。
本文对于段页管理机制只想通俗地说明一些概念,段页管理机制是分段式管理和分页式管理的组合,段式管理是逻辑上的管理方式,分页管理是偏物理上的管理方式。
计算机里面的一些技术和实现都可以在现实生活中找到缩影,所谓艺术和科技源自生活大概就是这个意思吧。
举个栗子: 在进行居民户籍管理时都会有区县市的概念,但是实际上并没有这种实体,都是逻辑上的,增加了这些行政单位之后可以让地址管理更加直接。
对于我们居民来说唯一的实体就是自己的房子住所,这是物理上的单位,是真实存在的,这也是最基本的单位。
对比linux段页时管理来说,段是逻辑上的单位相当于区县市的概念,页是物理上的单位相当于小区/房屋的概念,这样就方便很多。
多级页表也很好理解,总的物理内存假如有4GB,页大小为4KB,那么就总共有2^20个页,数量还是非常大的,这样编号来建立索引寻址比较不方便,所以引入多级页表,来减少存储便于管理。
段页机制加持下的逻辑地址和物理地址的映射关系简图,也就是虚拟地址到物理地址的对应关系:
图片来自网络
内存管理单元( MMU Memory Management Unit )是硬件层组件,主要提供将虚拟地址映射为物理地址。
MMU 的工作流程:CPU 生成逻辑地址交给分段单元,分段单元进行处理将逻辑地址转换为线性地址,再线性地址交给分页单元,分页单元根据页表映射转换内存物理地址,其中可能出现缺页中断。
缺页中断( Page Fault )是只当软件试图访问一个虚拟地址时,经过段页转换为物理地址之后,此时发现该页并没有在内存中,这时 cpu 就会报出中断,再进行相关虚拟内存的调入工作或者分配工作,如果出现异常也可能直接中断。
前面说的段页管理机制算是虚拟空间的部分,然而linux内存管理的另外一个重要部分就是物理内存的管理了,也就是如何分配和回收物理内存,这就涉及到一些内存分配算法和分配器。
分配器和分配算法就像公司财务,内存就像公司资金,如何把资金合理使用是财务的本职工作,如何把物理内存合理使用是分配器的分内之事。
如果我们不知道内存碎片是什么,试想一下我们常说的碎片化的时间,也就是那些虽然空闲但是没有被利用的时间,其实内存也是如此。
无论是时间还是内存被碎片化之后都无法被有效利用,因此合理管理减少碎片对我们来说是至关重要的,这也是物理内存分配算法和分配器的研究重点。
按照碎片的位置和产生原因,内存碎片分为外部碎片和内部碎片,我们看下这两种碎片的直观展示:
图片来自网络
从图中可以知道,外部碎片是进程与进程间未分配的内存空间,外部碎片的出现和进程频繁的分配和释放内存有直接关系,这个很好理解,模拟一下分配不同空间的进程不同时间释放就可以看到外部碎片的产生了。
内部碎片主要因为分配器粒度问题以及一些地址限制导致实际分配的内存大于所需内存,这样在进程内部就会出现内存空洞。
虽然虚拟地址让进程使用的内存在物理内存上是离散的,但是很多时候进程需要一定量连续物理内存,如果大量碎片存在,就会造成无法启动进程的问题,如图Process7需要一块连续的物理内存却无法被分配:
图片来自网络
如果还是没有很清楚,试想一下平时和三五好友去食堂吃饭或者坐公交的场景,整个车厢都没有连续的3个座位,所以要么分开坐要么都站着:
linux将物理内存按照页来划分,内存页的大小在不同的软硬件中可能不一样,linux内核设置为4KB,有的内核可能更大也可能更小,当时不同的大小在实际中都是有考量的,就像面包一样有大有小,并不是整齐划一的。
在内核中为了建立对物理内存页page的使用情况的监控,会有struct page这样的数据结构来记录页的位置地址/使用情况等,相当于内核对内存页管理的一本账目。
linux系统有内核态和用户态之分,内核态申请内存就立刻满足并且认为这个请求一定是合理的。然而用户态申请内存的请求,总是尽量延后分配物理内存,所以用户态进程是先获得一个虚拟内存区,在运行时通过缺页异常获得一块真正的物理内存,我们执行 malloc 时获取的只是虚拟内存而已,并不是真实的物理内存,也是这个原因造成的。
第一次听到这个算法名称就很好奇为什么叫伙伴系统?让我们来一起揭秘。
伙伴系统算法是解决外部碎片的有力工具,简单来说它针对频繁请求和释放不同大小的一组连续页框的场景,建立一套管理机制来高效的分配和回收资源,降低外部碎片。
第一种思路:把已经存在的外部碎片通过新的技术把这些非连续的空闲内存映射到连续的线性空间,其实相当于没有去降低外部碎片的产生而是治理型方案,但是这种方案在真实需要连续物理内存时是无效的。
第二种思路:把这些小的空闲的不连续内存记录在案,如果有新的分配需求就从中搜索合适的将空闲内存分配出去,这样就避免了在新的区域进行分配内存,有种变废为宝的感觉,其实这样场景也很熟悉当你想吃一包饼干时,你妈妈肯定会说先把之前剩下一半没吃完的吃掉,不要先开新的了。
基于一些其他方面的考量,linux内核选择了第二种思路来解决外部碎片。
在伙伴系统中把大小相同且物理地址连续的两块内存区域称为伙伴,连续地址的要求其实是比较苛刻了,但是这也是算法的关键,因为这样的两块内存区域可以合并成一块更大的区域。
伙伴系统将不同大小的连续物理页框进行管理,在申请时从最接近的页框大小进行分配,剩余的进行新的拆解,并将有伙伴关系的内存会进行合并成为大的页框。
伙伴系统维护了 n=0~10 共 11 个块链表,每个块链表分别包含了大小为 2^n 个连续的物理页。当 n=10 时即 1024 个 4KB 页对应 4MB 大小的连续物理内存块,这里的 n称为 order,在伙伴系统中 order为0~10,也就是最小的是 4KB,最大的内存块是4MB,这些相同大小的物理块组成双向链表进行管理,如图展示了 order=0 和 order=2 的两个双向链表的情况:
图片来自网络
申请内存过程:假设请求一个页框块,伙伴系统算法先在 order=0 的链表中检查是否有空闲块可分配。如果没有则查找下一个更大的块,在 order=1 的链表中找一个空闲块,链表中存在就把2个页框拆分,1个页框分配出去1 个页框加入到 order=0的链表中。如果 order=1 的链表中仍未找到空闲块,就继续向更大的order搜索,如果找到进行拆分处理,如果最终至 order=10 的链表也没有空闲块,则算法报错。
合并内存过程:合并内存的过程是伙伴算法中伙伴块的体现,算法把两个块具有相同大小 A且它们物理地址连续的内存合并为一个大小为 2A 的单独块。伙伴算法是自底向上迭代合并的,其实这个过程和 leveldb 中 sst 的合并过程很相似,区别在于伙伴算法要求内存块是连续的,这个过程也体现了伙伴系统对于大块内存的友好。
图片来自网络
伙伴系统算法较好地解决了外部碎片问题,并且对于大内存块的分配比较友好小粒度的内存可能造成内部碎片,但是伙伴系统对于伙伴块的定义很苛刻,并且在合并伙伴块的过程涉及较多的链表操作,对于一些频繁的申请可能刚合并就会被拆分掉,这就做了无用功,所以伙伴系统还是存在一些问题的。
从伙伴系统的介绍可以知道其分配的最小单位是 4KB 的页框,这对于一些频繁申请的小到几十字节的内存来说还是十分浪费的,所以我们需要更细粒度的分配器,这就是slab分配器。
slab分配器并不是和伙伴系统分立的,而是建立在伙伴系统之上,可以看作是伙伴系统的二级分销商,更加靠近用户侧,但是slab分配器因为更靠近使用方,因此在结构实现上比伙伴系统更加复杂,本文只能简单概括。
个人感觉slab分配器的亮点包括:最小粒度为对象和内存惰性归还。
Linux 所使用的 slab 分配器的基础是 Jeff Bonwick 为 SunOS 操作系统首次引入的一种算法。Jeff 的分配器是围绕对象缓存进行的。在内核中,会为有限的对象集(例如文件描述符和其他常见结构)分配大量内存。Jeff 发现对内核中普通对象进行初始化所需的时间超过了对其进行分配和释放所需的时间。因此他的结论是不应该将内存释放回一个全局的内存池,而是将内存保持为针对特定初始化的状态。
from 《linux slab 分配器剖析》
slab采用对象作为最小单位的理论基础就在于初始化一个结构的时间可能超过了分配和释放的时间。
slab分配器可以看作是一种内存预分配机制,就像超市会把常用的物品放到大家更容易找到的位置,事先把这些对象准备好申请时就可以立刻分配出去了。
slabs_full:链表中slab已经完全分配出去
slabs_partial:链表中的slab部分已经被分配出去了
slabs_empty: 链表中的slab都是空闲的 也就是可以被回收
对象是从 slab 中进行分配和释放的,每个kmem_cache的slab列表是存在状态迁移的,但是被回收的部分slab并不会立刻归还给伙伴系统,并且在分配时会优先分配最近被释放的对象,目的是利用cpu缓存的局部性原理,可以看出来slab分配器的细节做的很足,但是为了实现这一套复杂的逻辑,就要维护多个队列会比伙伴系统更复杂。
slab的内容相比buddy更复杂,本文不再展开。
linux内存管理的东西确实非常多,本文也只有5k字并且没有源码,所以只能是浅谈。
从工程角度来说,本文也只是抛砖引玉的作用,所以这篇文章并不是深入的探讨内存管理,对此我也表示歉意。
让我的好朋友sy审稿了一下,他说看着写了很多但又好像啥也没写,其实我跟他的感受一样,可能最近写文章没感觉,和上篇快手面试题差不多,写完之后有点迷茫。
所以最后还是那句话,本文只是浅谈,深入理解还是需要去看内核书籍,没有捷径。
本文由哈喽比特于4年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/3p2KnrYPkLwGJZ8FjPjOqQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。