免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1403 | 回复: 4
打印 上一主题 下一主题

[内核入门] 内存管理重要数据结构 [复制链接]

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-09-18 18:53 |只看该作者 |倒序浏览
本帖最后由 _nosay 于 2016-09-18 23:11 编辑

  • 内存管理的本质
    之前提到过,硬件的思想源于硬件本身,软件基于硬件的特性,可以对硬件进行控制,而“管理”相对于“控制”,可以认为是提升了一个高度,是指“合理的控制”,代表一种意愿。对于Linux的内存管理,就是希望所有进程可以和平共处的使用内存,以及更充分的使用内存。为此,Linux内核就需要维护一个账本,对整个系统中的内存信息,进行详细的记录,这样一来,就不会出现“把分配给进程A的内存又分配给进程B”等等意外的事情。
    日常生活中,政府机关分层级关系,上级管理着各个下级,最终细化到由派出所管理当地的每个人,管理者总会为被管理者建立管理信息,比如派出所有每个人的档案。计算机的方方面面,其实都借鉴于日常生活,内存管理也是如此,它为各个硬件建立管理信息(数据结构),并按层级维护好这些结构之间的关系。

  • 物理内存管理重要数据结构
    ① struct page
    系统启动之前,BIOS里面的一段程序,会将内存大小、磁盘等硬件信息收集起来,Linux内核再根据此信息,建立一个struct page mem_map[]数据,“mem_map[0]、mem_map[1]、……”依次表示“0~4K、4~8K、……”这些区间的内存信息,直到内存条中每个4K内存块都有对应的page结构。
   
    每个这样结构的信息,都描述了和它对应的4K物理内存(一个物理页面)的状态,比如某个物理页面空闲时,就将对应page的list成员挂入空闲区;可以通过lru挂入不活跃脏/干净链表;当物理页面用于文件缓存时,通过buffers表示与该页面缓存着哪些磁盘块的内容;等等(等学到具体章节时,具体介绍)。

    ② struct zone_struct
    将一根内存条看作一个物理页面仓库,zone_struct结构则是用于将这个仓库划分区域,一般分为ZONE_DMS、ZONE_NORMAL两个管理区,或再加一个ZONE_HIGHMEM管理区。至于分什么划分管理区,是个值得体会的问题,简单点理解,就像跟“国家分为省,省分为市……”是一个道理。
        成员free_area[],是一个双向链表头数组(之前已经介绍过list.h),free_area[N]链表头链接的都是2^N的连续空闲页面块(连续指的是在mem_map[]数组中下标连续),这样做有两个好处:
    ① 一块连续的页面块,只需要执行一次挂入操作,不需要对每个page的list都执行一次挂入链表头的操作,比如mem_map[0]~mem_map[127]对应的128个页面都空闲,只需要将mem_map[0]这个page挂入free_area[7]的链表头即可;
    ② 有时候分配内存,不只对大小有要求,还要求成块(即连续),所以如果每个页面单独的挂到链表头,当需要成块的物理内存时,再去找就很麻烦。

    为了满足这样的结构,分配/释放内存时,就需要做一些额外的操作:
    首先,当需要分配连续的页面块时,优先到恰好满足的链表头去找,如果没找到,依次加大下标,顺着free_area[]数组中的链表头找,如果找到,就通过“切割”大块得到最终需要的小块。比如,现需要分配连续8个页面,并且假设free_area[3]、free_area[4]、free_area[5]的链表头都为空,直到free_area[6]的链表头才不为空,就可以从free_area[6]取一个64连续页面块,并将其“切割”为一个32连续页面块、一个16连续页面块、两个8连续页面块,分别挂到free_area[5]、free_area[4]、free_area[3]的链表头上,这时就可以分配8连接页面块了。
    其次,释放的时候,要尽量将释放的内存块与已有的“碎片”合并。比如释放一个8连续页面块,就要判断是否可以与free_area[3]链表中某个8连续页面块合并,并转移到free_area[4]链表头上,如果合并成一个16连续页面块,要断续判断是否可以与free_area[4]链表中某个16连续页面块合并,依此类推……

    以下是伙伴系统算法的精确介绍:
  
    @ mem_map[]所有页面的空闲状态,由一个大的位图表示(bit);
    @ 蓝:busy,黑:空闲;order(n) - 0:不可以合并,1:可以合并;
    @ 上层对下层都按照(2n,2n+1)划分伙伴关系,比如order(0)对pages[]按照0-1、2-3……,而不是1-2、3-4……;
    @ 伙伴中的两个成员都空闲,这对伙伴才为空闲状态;
    @ 伙伴中的两个成员状态不同时,被分配的那个成员释放时,才可以合并成一个更大的块:
        比如10,11,由于10是空闲的,不可能被释放,而11被释放后,就可以和10合并成大块
        对于8,9,由于都是空闲的,本来就是合并的,就谈不上可不可以被合并,用0表示

    伙伴算法用于释放内存时,提高合并效率,避免遍历链表判断地址连续性。但也明显有缺陷,它只能将(2n,2n+1)划分为一对伙伴,比如1空闲,2被释放,它们就不能合并成块。

    ③ struct pglist_data
    ①②介绍的数据结构,用于管理单个内存条上的物理内存,当系统中有多个内存条时,各自信息由一个pglist_data数据结构描述:
   
    成员node_zonelists[]表示多种分配策略,每个数组元素包含一个zones[],表示一种分配策略,即优先从哪个管理区分配,如果分配失败,依次去哪些管理区进行第二次尝试。

  • 虚拟内存管理
    之前提到过,虚拟地址(用于描述逻辑的“代号”)也是资源,所以也需要管理。进程刚创建时,程序本身的指令和数据需要占用一些“代号”,在执行过程中,动态分配/释放内存时,“代号”也要跟随的动态分配/释放。

   
    随着进程的执行,一般会产生多个虚拟地址区间,每个区间由一个vm_area_struct结构记录,区间划分的依据是地址和属性,即使地址连续,如果属性不同,也不属于同一个区间。什么是属性呢?比如有些区间是存指令的,有些区间是存数据的,那么就属于不同的属性。
    进程中虚拟地址区间不是很多时,用链表结构管理即可,vm_next就是用于这个目的,当数量比较多时,就要用avl树结构管理,提高查询速度,所以含有成员vm_avl_height、vm_avl_left、vm_avl_right;
    如果映射/对应的物理页面被换出到磁盘,所有有一些记录与磁盘之间联系的成员:mapping、vm_next_share、vm_pprev_share、vm_file;

    vm_area_struct仅仅代表进程的某个虚拟区间,所以需要一个更全局的管理结构,那就是代表整个进程虚拟空间的mm_struct结构:
   
    这些结构中的成员,在后面学习内核管理的各种细节时,通过代码分析,自会理解,所以先对这些结构名称以及设计这个结构的目的,大致有个印象即可。

评分

参与人数 1可用积分 +6 收起 理由
Godbach + 6 赞一个!

查看全部评分

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2016-09-19 07:04 |只看该作者
回复 1# _nosay

赞一个! 感谢分享

论坛徽章:
1
2017金鸡报晓
日期:2017-01-10 15:13:29
3 [报告]
发表于 2016-09-19 19:19 |只看该作者
感谢分享,默默的看完了

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2016-07-08 21:00:1415-16赛季CBA联赛之同曦
日期:2017-02-15 14:26:1515-16赛季CBA联赛之佛山
日期:2017-02-20 14:19:2615-16赛季CBA联赛之青岛
日期:2017-05-07 16:49:1115-16赛季CBA联赛之广夏
日期:2017-07-30 09:13:1215-16赛季CBA联赛之广东
日期:2018-07-05 22:34:3615-16赛季CBA联赛之江苏
日期:2018-09-03 12:10:2115-16赛季CBA联赛之上海
日期:2018-09-25 03:49:2215-16赛季CBA联赛之广东
日期:2018-09-25 04:09:12
4 [报告]
发表于 2016-09-19 20:12 |只看该作者
回复 3# philarlala

谢谢你看完了

论坛徽章:
0
5 [报告]
发表于 2016-09-27 17:10 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP