Linux内存管理详解.docx

上传人:小飞机 文档编号:4886083 上传时间:2023-05-21 格式:DOCX 页数:16 大小:367.05KB
返回 下载 相关 举报
Linux内存管理详解.docx_第1页
第1页 / 共16页
Linux内存管理详解.docx_第2页
第2页 / 共16页
Linux内存管理详解.docx_第3页
第3页 / 共16页
Linux内存管理详解.docx_第4页
第4页 / 共16页
Linux内存管理详解.docx_第5页
第5页 / 共16页
亲,该文档总共16页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《Linux内存管理详解.docx》由会员分享,可在线阅读,更多相关《Linux内存管理详解.docx(16页珍藏版)》请在三一办公上搜索。

1、虚拟地址即使是现代操作系统中,内存依然是计算机中很宝贵的资源,看 看你电脑几个T固态硬盘,再看看内存大小就知道了。为了充分利用和管理系统内存资源,Linu x采用虚拟内存管理技 术,利用虚拟内存技术让每个进程都有4GB互不干涉的虚拟地址空间。 进程初始化分配和操作的都是基于这个虚拟地址,只有当进程需 要实际访问内存资源的时候才会建立虚拟地址和物理地址的映射,调 入物理内存页。打个不是很恰当的比方,这个原理其实和现在的某某网盘一样。 假如你的网盘空间是1TB,真以为就一口气给了你这么大空间吗?那 还是太年轻,都是在你往里面放东西的时候才给你分配空间,你放多 少就分多少实际空间给你,但你和你朋友看

2、起来就像大家都拥有1TB 空间一样。虚拟地址的好处o避免用户直接访问物理内存地址,防止一些破坏性操作,保护操作系 统o每个进程都被分配了 4GB的虚拟内存,用户程序可使用比实际物理内 存更大的地址空间4GB的进程虚拟地址空间被分成两部分:用户空间和内核空间用户空间内核空间艺程m .用户空间进程c .用户空间W程A 用户空间 3GB物理地址上面章节我们已经知道不管是用户空间还是内核空间,使用的地 址都是虚拟地址,当需进程要实际访问内存的时候,会由内核的请 求分页机制产生缺页异常调入物理内存页。把虚拟地址转换成内存的物理地址,这中间涉及利用MMU内存管 理单元(Me mo ry M an age

3、me nt U ni t )对虚拟地址分段和分页(段 页式)地址转换,关于分段和分页的具体流程,这里不再赘述,可以 参考任何一本计算机组成原理教材描述。aw g以地址;段页式内存管理地址转换Linux内核会将物理内存分为3个管理区,分别是:ZONE DMADMA内存区域。包含0MB16MB之间的内存页框,可以由老式基于ISA的设备通过DMA使用,直接映射到内核的地址空间。ZONE NORMAL普通内存区域。包含16MB89 6MB之间的内存页框,常规页框,直接 映射到内核的地址空间。ZONE HIGHMEM高端内存区域。包含896 MB以上的内存页框,不进行直接映射,可以 通过永久映射和临时映

4、射进行这部分内存页框的访问。物理内存区划分用户空间用户进程能访问的是用户空间,每个进程都有自己独立的用户空间,虚拟地址范围从从0x 00 00 00 00至0x BF FF FF FF总容量3G。用户进程通常只能访问用户空间的虚拟地址,只有在执行内陷操 作或系统调用时才能访问内核空间。进程与内存进程(执行的程序)占用的用户空间按照访问属性一致的地址 空间存放在一起的原则,划分成5个不同的内存区域。访问属性指 的是“可读、可写、可执行等。o代码段代码段是用来存放可执行文件的操作指令,可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作, 它是不可写的。o数据段数据段用来

5、存放可执行文件中已初始化全局变量,换句话说就是 存放程序静态分配的变量和全局变量。BSS段BSS段包含了程序中未初始化的全局变量,在内存中bss段全部 置零。堆 h ea p堆是用于存放进程运行中被动态分配的内存段,它的大小并不固 定,可动态扩张或缩减。当进程调用mall oc等函数分配内存时,新 分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释 放内存时,被释放的内存从堆中被剔除(堆被缩减)。栈 s ta ck栈是用户存放程序临时创建的局部变量,也就是函数中定义的变 量(但不包括st at ic声明的变量,sta ti c意味着在数据段中存放变 量)。除此以外,在函数被调用时

6、,其参数也会被压入发起调用的进 程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由 于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这 个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。 上述几种内存区域中数据段、BSS段、堆通常是被连续存储在内存中, 在位置上是连续的,而代码段和栈往往会被独立存放。堆和栈两个区 域在i3 86体系结构中栈向下扩展、堆向上扩展,相对而生。你也可以在linux下用si ze命令查看编译后程序的各个内存区 域大小:lemon # size /usr/local/sbin/sshd text data bss dec hex fil

7、ename1924532 12412 426896 2363840 2411c0 /usr/local/sbin/sshd内核空间在x86 3 2位系统里,Linux内核地址空间是指虚拟地址从 0xC0 00 00 00开始到0xFF FF FF FF为止的高端内存地址空间,总计1G 的容量,包括了内核镜像、物理页面表、驱动程序等运行在内核空间直接映射区直接映射区Direct Me mo ry Reg io n :从内核空间起始地址开始, 最大89 6M的内核空间地址区间,为直接内存映射区。直接映射区的89 6MB的线性地址直接与物理地址的前 896M B进行映射,也就是说线性地址和分配的物理

8、地址都是连续的。 内核地址空间的线性地址0x C0 00 00 01所对应的物理地址为 0x00 00 00 01,它们之间相差一个偏移量PAG E_ OFFSET = 0xC0 00 00 00该区域的线性地址和物理地址存在线性转换关系线性 地址二PA GE _O FF SET +物理地址也可以用vi rt _t o_ ph ys()函数将 内核虚拟空间中的线性地址转化为物理地址。高端内存线性地址空间内核空间线性地址从896M到1G的区间,容量128 MB的地址 区间是高端内存线性地址空间,为什么叫高端内存线性地址空间?下 面给你解释一下:前面已经说过,内核空间的总大小1GB,从内核空间起始

9、地址开 始的8 96 MB的线性地址可以直接映射到物理地址大小为896 MB的 地址区间。所以,内核空间拿出了最后的128M地址区间,划分成下面三个 高端内存映射区,以达到对整个物理地址范围的寻址。而在64位的 系统上就不存在这样的问题了,因为可用的线性地址空间远大于可安 装的内存。动态内存映射区vmal lo c Reg io n 该区域由内核函数vmal loc来分配,特点是: 线性空间连续,但是对应的物理地址空间不一定连续。vmal loc 分 配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内 存。永久内存映射区Persistent K er nel Mapping Re g

10、i on该区域可访问高端内存。访问方法是使用all oc_p age (_ GF P_H IG HM EM )分配高端内存页 或者使用kmap函数将分配到的高端内存映射到该区域。固定映射区F i xi ng k er ne l Map p in g Re gi on 该区域和 4G 的顶端只有 4k 的隔离带,其每个地址项都服务于特定的用途,如AC PI _B ASE等。4KB固定内有映莉区4MB860M-4G永久内有映射区4MB动态内存吸射区ZONE NORMALZONE DMA880 M安生保护区域8MB内校空三内核空间物理内存映射上面讲的有点多,先别着急进入下一节,在这之前我们再来回顾

11、一下上面所讲的内容。如果认真看完上面的章节,我这里再画了一张 图,现在你的脑海中应该有这样一个内存管理的全局图。内核空间用户空间全图邮内存或由安呈保护区成苴撬岫 呈1龄总计1网M的 遂世地扯盼罪.初瞳地扯J埋程日 m司 3GBJ进程匚 丑户兰同SG8内楼空乓 1GE永久内存虹区 4M33=5J瞧A 明户空间 3GBM -Isap堆 HeapESSvm area structvni_area_structvni_area_5tructwm_arem_structvm area struct代高爵内存数据结构要让内核管理系统中的虚拟内存,必然要从中抽象出内存管理数 据结构,内存管理操作如分配、释放

12、等都基于这些数据结构操作, 这里列举两个管理虚拟内存区域的数据结构。用户空间内存数据结构在前面进程与内存章节我们提到,Linux进程可以划分为5 个不同的内存区域,分别是:代码段、数据段、BSS、堆、栈,内核管 理这些区域的方式是,将这些内存区域抽象成vm_area_st ruc t的内 存管理对象。vm_a re a_ st ru ct是描述进程地址空间的基本管理单元,一个进 程往往需要多个vm_a r ea _s tr uc t来描述它的用户空间虚拟地址,需 要使用链表和红黑树来组织各个 vm_ ar ea _s tr uc t。链表用于需要遍历全部节点的时候用,而红黑树适用于在地址空 间

13、中定位特定内存区域。内核为了内存区域上的各种不同操作都能获 得高性能,所以同时使用了这两种数据结构。用户空间进程的地址管理模型:广vni_area_gtruct戋5tac(I:内核空间动态分配内存数据结构在内核空间章节我们提到过动态内存映射区,该区域由内核 函数vm alloc来分配,特点是:线性空间连续,但是对应的物理地址 空间不一定连续。vm alloc 分配的线性地址所对应的物理页可能处 于低端内存,也可能处于高端内存。vmal lo c 分配的 地址 贝。限于 vm al lo c_s t ar t 与 vm al lo c_e nd 之 间。每一块vma ll oc分配的内核虚拟内存

14、都对应一个vm_s tr uct结 构体,不同的内核空间虚拟地址之间有4k大小的防越界空闲区间隔区。与用户空间的虚拟地址特性一样,这些虚拟地址与物理内存没有 简单的映射关系,必须通过内核页表才可转换为物理地址或物理页, 它们有可能尚未被映射,当发生缺页时才真正分配物理页面。vmellos 分配地址4K井配地眦4K 问晦vmjillQCvm strud:vm structvm struct4 KB回定内存独沂区 4MB永久内存财/区 4MB8KB:V动态内痒山生区安全即区域 &M6宜接理射区 壕小&96 M跋住地址唳王到!RD理明批8,狗;.;上一百完三顽动态内存映射前面分析了 Linux内存管

15、理机制,下面深入学习物理内存管理 和虚拟内存分配。通过前面的学习我们知道,程序可没这么好骗,任你内存管理把 虚拟地址空间玩出花来,到最后还是要给程序实实在在的物理内存, 不然程序就要罢工了。所以物理内存这么重要的资源一定要好好管理起来使用(物理内 存,就是你实实在在的内存条),那么内核是如何管理物理内存的呢? 物理内存管理在Linux系统中通过分段和分页机制,把物理内存划分4K大小 的内存页Pa ge (也称作页框Pa ge F ram e),物理内存的分配和回收 都是基于内存页进行,把物理内存分页管理的好处大大的。假如系统请求小块内存,可以预先分配一页给它,避免了反复的 申请和释放小块内存带

16、来频繁的系统开销。假如系统需要大块内存,则可以用多页内存拼凑,而不必要求大 块连续内存。你看不管内存大小都能收放自如,分页机制多么完美的 解决方案!But,理想很丰满,现实很骨感。如果就直接这样把内存分页使用, 不再加额外的管理还是存在一些问题,下面我们来看下,系统在多次 分配和释放物理页的时候会遇到哪些问题。物理页管理面临问题物理内存页分配会出现外部碎片和内部碎片问题,所谓的内部 和外部是针对页框内外而言,一个页框内的内存碎片是内部 碎片,多个页框间的碎片是外部碎片。外部碎片当需要分配大块内存的时候,要用好几页组合起来才够,而系统 分配物理内存页的时候会尽量分配连续的内存页面,频繁的分配与回

17、收物理页导致大量的小块内存夹杂在己分配页面中间,形成外部碎片, 举个例子:脖邰内存捽片外部碎片内部碎片物理内存是按页来分配的,这样当实际只需要很小内存的时候, 也会分配至少是4K大小的页面,而内核中有很多需要以字节为单位 分配内存的场景,这样本来只想要几个字节而已却不得不分配一页内 存,除去用掉的字节剩下的就形成了内部碎片。内部碎片页面管理算法方法总比困难多,因为存在上面的这些问题,聪明的程序员灵机 一动,引入了页面管理算法来解决上述的碎片问题。Buddy (伙伴)分配算法L inux内核引入了伙伴系统算法(Bu dd y sys te m),什么意思呢? 就是把相同大小的页框块用链表串起来,

18、页框块就像手拉手的好伙伴, 也是这个算法名字的由来。具体的,所有的空闲页框分组为11个块链表,每个块链表分别包 含大小为 1,2,4,8,16,32,64,128,25 6,51 2 和 10 24 个连 续页框的页框块。最大可以申请102 4个连续页框,对应4MB大小的 连续内存。伙伴系统因为任何正整数都可以由2” n的和组成,所以总能找到合适大小 的内存块分配出去,减少了外部碎片产生。分配实例比如:我需要申请4个页框,但是长度为4个连续页框块链表没 有空闲的页框块,伙伴系统会从连续8个页框块的链表获取一个,并 将其拆分为两个连续4个页框块,取其中一个,另外一个放入连续4 个页框块的空闲链表

19、中。释放的时候会检查,释放的这几个页框前后 的页框是否空闲,能否组成下一级长度的块。命令查看lemon# cat /proc/buddyinfoNode 0, zone DMA 1 0 0 0 2 1 1 0 1 1 3Node 0, zone DMA32 3198 4108 4940 4773 4030 2184 891 18067 32 330Node 0, zone Normal 42438 37404 16035 4386 610 121 22 30 0 1slab分配器看到这里你可能会想,有了伙伴系统这下总可以管理好物理内存 了吧?不,还不够,否则就没有slab分配器什么事了。那什么

20、是slab分配器呢?一般来说,内核对象的生命周期是这样的:分配内存-初始化-释 放内存,内核中有大量的小对象,比如文件描述结构对象、任务描述 结构对象,如果按照伙伴系统按页分配和释放内存,对小对象频繁的 执行分配内存-初始化-释放内存会非常消耗性能。伙伴系统分配出去的内存还是以页框为单位,而对于内核的很多 场景都是分配小片内存,远用不到一页内存大小的空间。slab分配器, 通过将内存按使用对象不同再划分成不同大小的空间,应用于内 核对象的缓存。伙伴系统和slab不是二选一的关系,slab内存分配器是对伙 伴分配算法的补充。原理对于每个内核中的相同类型的对象,如task_ struct、file

21、 _s tr uc t等需要重复使用的小型内核数据对象,都会有个sl ab 缓存池,缓存住大量常用的已经初始化的对象,每当要申请这种 类型的对象时,就从缓存池的slab列表中分配一个出去;而当要释放 时,将其重新保存在该列表中,而不是直接返回给伙伴系统,从而避 免内部碎片,同时也大大提高了内存分配性能。主要优点slab内存管理基于内核小对象,不用每次都分配一页内存,充分利用 内存空间,避免内部碎片。slab对内核中频繁创建和释放的小对象做缓存,重复利用一些相同的 对象,减少内存分配次数。数据结构kmem cacheslabs fullslabpageobjectkmem cacheslatjs

22、_parti3lpageobjectslabpageslabslabs_emptycache_criainobjectkmem_cacheIJslab分配器kmem_c ac he是一个cach e_ ch ai n的链表组成节点,代表的是一 个内核中的相同类型的对象高速缓存,每个kmem_ cache通常是 一段连续的内存块,包含了三种类型的slabs链表: slab s_ full (完全分配的sl ab链表) s l ab s_ pa rt ia l (部分分配的s la b链表)slab s_ empt y (没有被分配对象的sl ab链表)kmem_c ac he 中有个 重要的结构

23、体kmem _li st 3包含了以上三个数据 结构的声明。sti ul kmem_lLst3 (.ui - list .h-ed slabspartial; ”struct Yist_head slibs_full;幻闲的si日bJIS述格勺slruct Listhad 5labs_Free; WiH/islM!; 上、*unsiqid Long freezebjectsunsigned. inT free_limit j1unsigned tnt colou r_next;/* er-node cache ccfi_tf r rre ftuai o% EdHnrn i:K_*3pn: ek

24、J-tmT* iLTicrinr kJ 二日 mfr iLinHlJfii Mid jilt mdZjMd 母um Jit 】!,MhuXlImUUjlHk MIE “HUbkHIMIE9e flflp bjpnl通第 甲峭f事心口 feAablis:TuMJjliKI - TJUD EWI ; thiHtlffiI : TJU畦找4 : tauiblfifil : tdMblm1 : 1g 盹 tsI. taublK.2 s TJUtlKE - tLJUbKI i fUMbllK1 J tJUbkH2 d tMt-lne EujUfaff n dLIhUiblCt. 11B|.0 t _L#

25、iy I、 甲 中 中!: j : s Labda ia a i 卷la+dmim a r filaHW a ; tiLaFNia B I VlMriTA & : 5 LrHdia a i:时KNta 倒 I. i IJrtKlJUl B t f-Lairiau D r9 k 4*3忸 9 t tLlrMJla P L iLiMJUi c i海n cs0.93K rin n i- ri r5692t rcr34GL1S2144K ext4_inode_Gache n Jbn m r 11 n 10BJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE

26、 NAMEslabtop 查询slab高速缓存的分类slab高速缓存分为两大类,通用高速缓存和专用高速缓存。通用高速缓存s l ab分配器中用kme m_c ac he来描述高速缓存的结构,它本身也 需要slab分配器对其进行高速缓存。cach e_ ca ch e保存着对高 速缓存描述符的高速缓存,是一种通用高速缓存,保存在 cach e_ ch ai n 链表中的第一个元素。另外,slab分配器所提供的小块连续内存的分配,也是通用高 速缓存实现的。通用高速缓存所提供的对象具有几何分布的大小,范 围为32至0 131 07 2字节。内核中提供了 kma ll oc ()和kfr ee()两个

27、 接口分别进行内存的申请和释放。专用高速缓存内核为专用高速缓存的申请和释放提供了一套完整的接口,根据 所传入的参数为指定的对象分配slab缓存。专用高速缓存的申请和释放kmem_c ac he _c re ate ()用于对一个指定的对象创建高速缓存。 它从c ac he _c ac he普通高速缓存中为新的专有缓存分配一个高速缓 存描述符,并把这个描述符插入到高速缓存描述符形成的 c ach e_ ch ai n 链表中。km em _c ac he _de s to ry () 用于撤消和从 cach e_ ch ai n链表上删除高速缓存。slab的申请和释放slab数据结构在内核中的定

28、义,如下:st ruct slab struct Listhead list; /*:; slabiiAk&neunsigned long colonroff Jvoid +s_mem;- ; ;slab结构体内核代码kmem_c ac he _a ll oc()在其参数所指定的高速缓存中分配一个 slab,对应的kme m_ c ac he _f re e()在其参数所指定的高速缓存中 释放一个sl ab。虚拟内存分配前面讨论的都是对物理内存的管理,Linux通过虚拟内存管理, 欺骗了用户程序假装每个程序都有4G的虚拟内存寻址空间(如果这 里不懂我说啥,建议回头看下别再说你不懂Li nux内

29、存管理了,10张图给你安排的明明白白!)。所以我们来研究下虚拟内存的分配,这里包括用户空间虚拟内存 和内核空间虚拟内存。注意,分配的虚拟内存还没有映射到物理内存,只有当访问申请 的虚拟内存时,才会发生缺页异常,再通过上面介绍的伙伴系统和 slab分配器申请物理内存。用户空间内存分配mallocmall oc用于申请用户空间的虚拟内存,当申请小于128 KB小内 存的时,ma ll oc使用sbr k或br k分配内存;当申请大于12 8KB的内 存时,使用mmap函数申请内存;存在问题由于br k/ sb rk /m map属于系统调用,如果每次申请内存都要产生 系统调用开销,cpu在用户态和

30、内核态之间频繁切换,非常影响性能。 而且,堆是从低地址往高地址增长,如果低地址的内存没有被释放, 高地址的内存就不能被回收,容易产生内存碎片。解决因此,mal loc采用的是内存池的实现方式,先申请一大块内存, 然后将内存分成不同大小的内存块,然后用户申请内存时,直接从内 存池中选择一块相近的内存块分配出去。内核空间细分区域kmallockmalloc()分配的虚拟地址范围在内核空间的直接内存映射 区。按字节为单位虚拟内存,一般用于分配小块内存,释放内存对应 于kfr ee,可以分配连续的物理内存。函数原型在 中声明,一般情况下在驱动程序中都是调 用 kmalloc()来给数据结构分配内存。还

31、记得刖面说的sla b吗? kma ll oc是基于sl ab分配器的,同样可以用cat / pr oc/ sl ab in fo 命令,查看km al lo c相关sl ab 对象信息,下面的kmalloc-8、km al lo c-1 6等等就是基于s la b分配的 k ma ll oc高速缓存。uralLoc-BiHZ kitalloc -4096 knsaUoc-268 kjijdlldt-1024 kjrallac.-S12 kjiaalloc-256 kiralldc -192 kFallac-IQS kJFallflt-6 kfilloc -M- kjiallK-32 knsa

32、lioc:-163=71234970474960O2渤5)201UU 4妣 1024 152 31M 544 gg 2?40 QA6Q 19600 23D4 51204睥6 2048 1024 S12 256 192 123 56 &4 22 168 10 2 32 92 21 32 43 64 120 256H : runab lies 8 : tunables 8 : tunable 目=turidbleb 4 : tunables 2 : tunables 1 t tunables 1 - tunablAE; 1 : tunables 1 s tunables 1 e tunables

33、1 : tumablesO 0Q _A o o OGOOOOGQO0QGOOOsldbdata sldbdata slsbdata Idbddtd slabdata slabdata slabdata clahdata glabdata slabdata slabdata slabdata564F4770esg92 566G-1&7 & 7121 2 76 4 17 75 Av 1slabinfo-kmallocvmallocvmal lo c分配的 虚拟 地址区间,位于vm a ll oc _s ta rt与 vmal lo c_ en d之间的动态内存映射区。一般用分配大块内存,释放内存对应于vf ree,分配的虚拟内存 地址连续,物理地址上不一定连续。函数原型在 中声明。一般用在为活动的交换区分配数据结构,为某些I /O驱动程 序分配缓冲区,或为内核模块分配空间。下面的图总结了上述两种内核空间虚拟内存分配方式。内核正表物理内存 葬页框命恋内存映射区内禳程序I :二:A快律泉埃kmalloc总结Linux内存管理是一个非常复杂的系统,本文所述只是冰山一角, 从宏观角度给你展现内存管理的全貌,但一般来说,这些知识在你和 面试官聊天的时候还是够用的,当然也希望大家能够通过读书了解更 深层次的原理。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号