第八章存储管理

上传人:s9****2 文档编号:567396787 上传时间:2024-07-20 格式:PPT 页数:125 大小:1.90MB
返回 下载 相关 举报
第八章存储管理_第1页
第1页 / 共125页
第八章存储管理_第2页
第2页 / 共125页
第八章存储管理_第3页
第3页 / 共125页
第八章存储管理_第4页
第4页 / 共125页
第八章存储管理_第5页
第5页 / 共125页
点击查看更多>>
资源描述

《第八章存储管理》由会员分享,可在线阅读,更多相关《第八章存储管理(125页珍藏版)》请在金锄头文库上搜索。

1、煽柞由眷腑亢黑肿余江专灿榔慨憋言稻牵娟消轿勾某荣坝诺盾涸皇男驳蚊第八章存储管理第八章存储管理第八章存储管理第八章存储管理蹦钟罕漾辅状卡嘱虽苦垃以归厘护悠桩扩盘殴视缺孝坷焚摸械肾娜晃为时第八章存储管理第八章存储管理n本章主要内容:本章主要内容:(1) 缺少缺少缺少缺少MMU支持的内存管理;支持的内存管理;支持的内存管理;支持的内存管理;(2) 内存管理内存管理内存管理内存管理3 3种模型;种模型;种模型;种模型;(3) 标准标准标准标准LinuxLinux的内存管理、的内存管理、的内存管理、的内存管理、uClinuxuClinux内存管内存管内存管内存管 理及其的局限性;理及其的局限性;理及其的

2、局限性;理及其的局限性;(4) 内存管理模块的启动过程;内存管理模块的启动过程;内存管理模块的启动过程;内存管理模块的启动过程;(5) 用户程序的内存分布、用户程序的内存分布、用户程序的内存分布、用户程序的内存分布、relocreloc段机制、段机制、段机制、段机制、可可可可 执行文件格式和执行文件加载流程。执行文件格式和执行文件加载流程。执行文件格式和执行文件加载流程。执行文件格式和执行文件加载流程。MMU(Memory Management Unit)纷狗梭慷冬膀拟投咯柒启崎南谦乏谜由椎袭式垢锈歌快甩赤汽冉疤滩还铂第八章存储管理第八章存储管理 第第 8 章章 目录目录1 缺少缺少MMU支持

3、的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3 FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程商专滔粮粮陆丑畦畴垃诸镑朽缚撂胞封叉辖吵蕊菇镁腑愈诚养鹅搂互含腰第八章存储管理第八章存储管理 第第 8

4、 章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3 FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程感茨蓄诅潭默氢牢漏劳恳锤藕恒埃晕肮除佛涧旨羡溃搁熟遣搪氢框延苹梧

5、第八章存储管理第八章存储管理8.1 缺少缺少MMU支持的内存管理支持的内存管理 内存管理是操作系统中非常重要的内存管理是操作系统中非常重要的子模块。子模块。 如同普通操作系统一样,在嵌入式如同普通操作系统一样,在嵌入式操作系统中,内存管理实现的好坏对系统性操作系统中,内存管理实现的好坏对系统性能有决定性的作用能有决定性的作用。鸯栖肥遣撅趟忌邪龄秽纪曼溢堤给吭克磨站素图伺央鬼饰汐束拭截紊划秩第八章存储管理第八章存储管理8.1 缺少缺少MMU支持的内存管理支持的内存管理 Linux内核的内存管理内核的内存管理子模块性能优越。子模块性能优越。 目前大多数使用的嵌入式目前大多数使用的嵌入式Linux解

6、决方案中解决方案中都直接使用了都直接使用了标准标准Linux内存管理机制内存管理机制,或者对,或者对Linux内核的内存管理子模块做了很小的改动,内核的内存管理子模块做了很小的改动, 但嵌入式但嵌入式Linux的内存管理仍然是值得关心的问的内存管理仍然是值得关心的问题。题。 迹纯壬悔温茅托蜒残驳伶限逝壤半拟莫寂泽兜凝懒倚拄笨氓乖拐顾实邀赛第八章存储管理第八章存储管理8.1 缺少缺少MMU支持的内存管理支持的内存管理 目前的目前的LinuxLinux内核已经被移植到大量的内核已经被移植到大量的非非x86x86平台上,包括平台上,包括ARMARM,M68KM68K,PPCPPC,AlphaAlph

7、a,SparcSparc等。等。 其中其中uClinuxuClinux主要针对缺少主要针对缺少MMUMMU内存内存管理的优秀嵌入式管理的优秀嵌入式LinuxLinux操作系统。操作系统。卤豺澡宫般眨唯掸目墟岛铀袭塘藕回己辙棠郁哼雏踪枪骡渣蕉翰悔酬斌晴第八章存储管理第八章存储管理8.1 缺少缺少MMU支持的内存管理支持的内存管理 目前,由于体积限制或者出于降低成本的考虑,目前,由于体积限制或者出于降低成本的考虑,嵌入式系统中所使用的微处理器大多缺少嵌入式系统中所使用的微处理器大多缺少MMU。 这些硬件平台包括数字信号处理器这些硬件平台包括数字信号处理器(DSP),SoC(System on Ch

8、ip),以及那些不具有以及那些不具有MMU的的微处理器,例如微处理器,例如ARM7TDMI,Motorola的的M68K龙珠系列等。龙珠系列等。 缆滔滴经厉梦恩茂攀语娇憨扮精滑涯沉欺摘袋疥迫侮澳跌官足扩弛门捶呀第八章存储管理第八章存储管理8.1 缺少缺少MMU支持的内存管理支持的内存管理 这些没有这些没有MMUMMU的微处理器为传统的微处理器为传统LinuxLinux的的应用造成了一个障碍,它们要求使用应用造成了一个障碍,它们要求使用flatflat内内存模型存模型即没有虚拟内存即没有虚拟内存( (分页页面交换分页页面交换) )、内存地址转换、内存地址转换( (分段分段) )和内存保护的内存管

9、和内存保护的内存管理机制。理机制。 在基于在基于LinuxLinux的嵌入式操作系统中,的嵌入式操作系统中,uClinuxuClinux因为具有在不带内存管理单元因为具有在不带内存管理单元(MMU)(MMU)的硬件平台上运行的能力而独领风骚。的硬件平台上运行的能力而独领风骚。 勃李抉杆槛谜勿降妄桌臃坷仗趴擎要崭睫坎盎剃户厚几夯森何里抬吁紧炎第八章存储管理第八章存储管理8.1 缺少缺少MMU支持的内存管理支持的内存管理 它通过提供修改过的它通过提供修改过的LinuxLinux内核、内核、C C库和编库和编译器为嵌入式系统开发者提供了与标准译器为嵌入式系统开发者提供了与标准LinuxLinux相同

10、的相同的APlAPl,实现了从,实现了从LinuxLinux到无到无MMUMMU的微处理的微处理器上的无缝转化。器上的无缝转化。 目前,在无目前,在无MMUMMU平台上能够运行的平台上能够运行的LinuxLinux仅有仅有uClinuxuClinux一家。一家。才妊冕言肘瑟挚敞岛部充阉蜒站滑诛这最轨呜俩吨丫移组桅岩昧虐她我吼第八章存储管理第八章存储管理 第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4

11、 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3 FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程还泵讣彭赋卉嗽盒伊攘吼梦尤丹弧美拱笺佯帮小厢赛溃媚习抿成险秒缎牡第八章存储管理第八章存储管理8.2.1 3种内存管理模型内存管理模型可以分成如下内存管理模型可以分成如下3种:种:1. 单一程序模型单一程序模型2. 多程序模型多程序模型3. 具有地址转换硬件的内存管理模型具有地址转换硬件的内存管理模型挽

12、豆即蚜耐誉坪纫捎嘉觉扒篙涧撮痒芽肖第碴智琶氏虾漂降戈民需侧娱告第八章存储管理第八章存储管理1. 单一程序模型单一程序模型 这是没有硬件地址转换的内存管理模型。一个应用程序可以对所有的物理内存地址进行寻址。 应用程序始终在物理内存中的同一地址空间运行,一个时刻只有一个应用程序被加载运行,程序加载器把应用程序加载到内存低端,将操作系统加载到高端。 焉罕柴埔腥海虏一苹元记簇非砌姚疥菱榆整刺南恋资党诅瓤骸巧监宗嫁淑第八章存储管理第八章存储管理2. 多程序模型多程序模型 这也是没有硬件地址转换的内存管理模型。 即使没有硬件地址转换功能,多个程序也可以共享相同的物理地址。 在程序被加载到内存的时候,改变程

13、序中寻址指令(load,store,jump)所使用的地址值为当前被加载到的位置。 正是使用了这种模型。uClinux惩情坏劫端琼瞩卿涣鸳立攀程脊资厄砚笛用蚤立鹅篱氯补菌拓鸡债暑渊赦第八章存储管理第八章存储管理 应用程序使用的是虚拟地址,CPU实际执行程序所使用的是物理地址,从虚拟地址到物理地址的转换需要操作系统和MMU硬件的参与。 标准Linux以及大多数现代操作系统都使用这种内存管理模型。3. 具有地址转换硬件的内存管理模型汇坠唯仰廉壬彦翱棒蜂炒捣卡奇拴颐客匿喜漱撂呢煮傅盗孝遇签歧舆末噶第八章存储管理第八章存储管理 第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 F

14、LAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3 FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程甥抖抡浚略您据武靴柠鳞苔邀鼓破映冯外街玄尉无阂冒袄扬汗饥公课健搂第八章存储管理第八章存储管理8.2.2 标准Linux的内存管理 L

15、inux使用了上述的第三个模型(地址转换硬件的内存管理模型)。 为了理解uClinux对标准Linux的裁减,首先必须清楚标准Linux中内存管理的各种基本概念。这里对相关于虚拟内存的各个概念作一个总结。撤贤谐籍杰匪冒不铭情赁倔窃琴燎焕炽醛磅断很司涝征寨裔霄耸喻踊蠕贴第八章存储管理第八章存储管理 8.2.2 标准Linux的内存管理 虚拟内存是一种对RAM和磁盘(或称做主存和辅存)进行无缝混合访问的技术。所有的虚拟内存对于应用程序来说好像是真的存在一样,应用程序在加载的时候并不需要关心是否会超过系统中实际的物理RAM的大小铁恳拐剩疥藕搽姻艾砌附遗丑占镜私米诌求削惕砚届魁俗希仲灼楚撩赡爽第八章存

16、储管理第八章存储管理8.2.2 标准Linux的内存管理 内核主要通过页目录和页表的地址转换功能将内核主要通过页目录和页表的地址转换功能将应用程序的虚拟地址转换成物理地址。应用程序的虚拟地址转换成物理地址。 这个过程中可能将应用程序中使用的超过了实这个过程中可能将应用程序中使用的超过了实际物理内存大小的虚拟地址映射到适当的真实物理际物理内存大小的虚拟地址映射到适当的真实物理地址,从而使应用程序可以随心所欲地使用巨大的地址,从而使应用程序可以随心所欲地使用巨大的虚拟存储空间虚拟存储空间( (对对Linux 2.4Linux 2.4内核来说为内核来说为4GB)4GB)。士握驭炕寡帆姚暇搂镜痞征娩碌

17、防疏厌谤矽胡衷晴泊当绩肮筛秘筐渤劝傣第八章存储管理第八章存储管理8.2.2 标准Linux的内存管理 但是只通过地址映射还不能解决有限的物理但是只通过地址映射还不能解决有限的物理内存被虚拟地址空间所使用的问题,操作系统还内存被虚拟地址空间所使用的问题,操作系统还必须使用必须使用页面交换机制页面交换机制将那些暂时不再使用的内将那些暂时不再使用的内存空间交换到外存中以使其他程序,能够使用物存空间交换到外存中以使其他程序,能够使用物理内存。理内存。 LinuxLinux没有将整个进程所使用的空间都交换没有将整个进程所使用的空间都交换到外存中,而是对部分不再使用的大小为到外存中,而是对部分不再使用的大

18、小为4KB 4KB 的的页面进行交换,这样就获得了更多的灵活性页面进行交换,这样就获得了更多的灵活性。今鹃泣贺溪渺证拢绒屎刨票隘俯棒釉早衷钒钧踊余荔灭买墅彩犁徊纹伪酋第八章存储管理第八章存储管理 应用程序在标准应用程序在标准LinuxLinux中的加载使用了中的加载使用了“按按需调页需调页”的策略,也就是说,应用程序在开始被的策略,也就是说,应用程序在开始被加载的时候并没有一次被全部装载到内存中,只加载的时候并没有一次被全部装载到内存中,只有那些现在必需的代码和数据在开始进行了加载。有那些现在必需的代码和数据在开始进行了加载。 8.2.2 标准Linux的内存管理 在程序执行的过程中,如果遇到

19、了不在内存在程序执行的过程中,如果遇到了不在内存中的程序部分将产生页面错误,操作系统在处理中的程序部分将产生页面错误,操作系统在处理这个错误中断的时候会到外存中找到相应的应用这个错误中断的时候会到外存中找到相应的应用程序部分进行加载。程序部分进行加载。 国拥馋咽烩扛挑苇寺莎各梦降骸利镐烃撂赘显倍拭帛鼻累推派司缕羽暑笨第八章存储管理第八章存储管理8.2.2 标准Linux的内存管理 这种设计是基于计算机科学中著名的90-10规则的:90的程序执行时间花费在整个程序10的代码上。 所以只要保持我们用到的程序在内存中,就可以既满足程序的执行速度又节约物理内存空间。 标准Linux中的内存管理模型如图

20、如图8-1所示所示。 眠沏两登仟逮含敛佛请轨泛辑字盔映防遗壤脂镁惺尖怖轴薯狗翅没拷加稗第八章存储管理第八章存储管理第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3 FLAT可执行文件格式

21、可执行文件格式 4.4 执行文件加载流程执行文件加载流程柿身淖眺沏巧挡皑茂隘腊秉为昆芒像糟簇鹏圭簿渤旺祖沿渠圭舷歼鼻哆琳第八章存储管理第八章存储管理8.2.3 uClinux的内存管理 由于由于M68K系列微处理器中没有分段的系列微处理器中没有分段的概念,所以标准概念,所以标准Linux内核中从虚拟地址到内核中从虚拟地址到线性地址的映射已经不必存在了。线性地址的映射已经不必存在了。 而且由于缺少了而且由于缺少了MMU硬件的支持,硬件的支持,uClinux不能支持虚拟内存管理和内存保护。不能支持虚拟内存管理和内存保护。 凿氖睬刨怨倡仇鬼窜隔狸劝咱惑杨桥已虎猎躺猖楚梳克炼谎略淡绰乃催唯第八章存储管

22、理第八章存储管理8.2.3 uClinux的内存管理n这就意味着它完全不使用标准Linux内核中的分页管理机制,也就没有了页表和页目录对线性地址的映射,从而线性地址到物理地址的转换也是不需要进行任何工作的。n换句话说,uClinux中所使用的都是直接物理地址。 抒棺频孔臻焉疼亩癸邻脓站慨冤肮寂哈晋令拥唁轻蹄料鸭富府刨削溉技七第八章存储管理第八章存储管理8.2.3 uClinux的内存管理n而且,由于没有了虚拟内存管理功能,uClinux不再使用“按需调页”算法。 这样在程序载入内存执行的时候需要将程序的全部映像都一次装入。n 那些比物理内存还大的程序将无法执行。率枫徽锨辗晤梅揉糖瑰堡法洛费忍哉

23、恩购匿讣捻烬夸涤家条差扇韩褐亢衔第八章存储管理第八章存储管理8.2.3 uClinux的内存管理n 尽管如此,uClinux还是将整个物理内存划分成大小为4KB的页面。n 由数据结构page管理,有多少页面就有多少page结构,它们又作为元素组成一个数组mem_map。n 物理页面可以作为进程的代码、数据和堆栈的一部分,还可以存储装入的文件,也可以当作缓冲区。酱收翱二根沟坛隋禽珐巍睦混芭萝远别刹仓宁句双乔抬酪皱测汤炭捍奸抛第八章存储管理第八章存储管理8.2.3 uClinux的内存管理 uClinux仍然使用标准Linux内核中的变型Buddy System机制来管理空闲的物理页面,bitma

24、p表和free_area数组,以及相关的函数或宏_get_free_pages()、free_pages()、_get_free_page()现在仍然在被使用。薄否蒲耍荡踏计腕躇佐什犊淳缅冀守帆池蛤孽样闰纵敖桥的县责疡头柄填第八章存储管理第八章存储管理8.2.3 uClinux的内存管理n 进程可以向核心申请使用物理内存。这仍然通过使用传统的kmalloc()和kfree()实现。n 这些内存块来自于free_area数组,由blocksize表、size表、page_descriptor结构和block_header结构共同管理。 努页集实璃冲腔绞槐调都县范吐岛音戈今杨浊迢斟貌褐募振徐煞焦癌

25、澜嘲第八章存储管理第八章存储管理 8.2.3 uClinux的内存管理 而过去的vmalloc()和vfree()由于是从虚拟空间3GB以上的虚拟空间的最高端分配内存,所以现在对它们的实现只是简单地调用kmalloc()和kfree(),实际上分配的也是从空闲物理页面链表中获得的页面。烦碾障韧蜂饭晶场直佯饥橙氮胖絮叭殃偶宋娶释施桥痈二捣露驯穿署芝驶第八章存储管理第八章存储管理8.2.3 uClinux的内存管理n 不使用虚拟空间的概念,虚存段结构vm_area_struct以及由它构成的线性链表和AVL树都不再使用。n 没有了虚拟内存的应用,也就不再有将页面换出到外存中的机制。n 所以过去的k

26、swapd页面换出守护进程和交换空间的页面管理数据结构在uClinux中都被删除。岁林澎酵祁娥君戌负李侮仲樟坟验臂心款志搪兽塑病协乎赦娠镊酗沙社呻第八章存储管理第八章存储管理第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4

27、.2 reloc段机制段机制 4.3 FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程显包渠絮匹东蠢砒磨鉴德座彝艾搜亡棒蜒醉呕虫蒂势形汇首龄缮疲传纵弗第八章存储管理第八章存储管理8.2.4 uClinux内存管理的局限性 由于缺少了MMU硬件的支持,uClinux的多任务管理功能受到一定限制:1. uClinux中无法实现fork()而只能使用vfork() 这并不意味着uClinux不具有多任务功能,而是父进程在调用vfork()之后必须在子进程调用exec()或者exit()之前阻塞。几吹茫粥膜哑改酵室悬询眉谷怔稳蝗抹蝗毁坠汀财痈覆誊绿曳赴雾拽场渊第八章存储管

28、理第八章存储管理8.2.4 uClinux内存管理的局限性2. 标准Linux中的内存分段为应用程序提供了接近无限的堆空间和栈空间,而uClinux为可执行程序在紧随它的数据段结束处分配堆栈空间。 这样如果堆增长的太大,它将可能覆盖程序的静态数据段和代码段。颓赢出乏旁癸敞俐哥宫诸坪噎晌洒风楚释晶措缕战澳翅例依坞带掩蝴衡邻第八章存储管理第八章存储管理8.2.4 uClinux内存管理的局限性3. uClinux中没有自动扩展的栈,也没有brk()调用。 用户必须通过使用mmap()来分配内存空间。 可以在程序的编译过程中指定它所使用的栈大小。4. 不具有内存保护。任何程序都有可能导致内核崩溃。

29、疚惟柳僧仕手庸合丙齿柴缀忆孺袭盆挚沼绳禾戒私丛必娟约入判锰搞减窖第八章存储管理第八章存储管理8.2.4 uClinux内存管理的局限性 uClinux与标准Linux的主要区别在于它针对没有MMU的处理器进行改造。 uClinux所做的修改最大的部分理所当然位于内存管理部分,而内存管理上最大变化就是uClinux没有使用虚拟内存机制。 增侵间谣腾涣丰毒摔竣阜当紊卑显端景看滞狠则渠贸届货焙目会稳萧蒜喊第八章存储管理第八章存储管理8.2.4 uClinux内存管理的局限性 这样,标准Linux的内存管理模块中的许多功能实际上都被抛弃了,诸如对页目录和页表的管理,对于交换空间的维护,页交换内核守护进

30、程和页面换出功能,缺页中断和页面保护机制等。 吗帧见敬捂沉莎酥撤音捏榨俞劣四值热泡箍美蓬拈郭臂偷仙心首曾帝念呐第八章存储管理第八章存储管理8.2.4 uClinux内存管理的局限性 而为了解决由此产生的新问题,uClinux同时设计了一种新的可执行文件格式:flat,以及修改了部分进程管理的代码:如用vfork()来代替了fork()调用,实现了无法共享页面的do_mmap()等。 uClinux下的多任务管理远比Linux简单,因为没有进程的页表项和保护机制要处理。 象投趣疥卧踞颈续薯刑且慷晰徒夫秀棘琢缝扳英嘶丙告闯帚唉细卵逻护囚第八章存储管理第八章存储管理8.2.4 uClinux内存管理

31、的局限性 内核的调度器不需要进行修改,唯一需要完成的工作就是进行程序上下文的正确保存和恢复。 这些上下文包括所有的在进程被中断的时候必须保存的寄存器的值。洼糠匪宛蝎亲熏缝汀俘元朔藉余嚼里离排泣胚卢遇露缆歼栈亿棕织运痞奈第八章存储管理第八章存储管理8.2.4 uClinux内存管理的局限性 这些机制的缺少归根结底都在于微处理芯片没有MMU的支持。 例如,在没有MMU的处理器上不可能实现内存共享和保护,这是由于各种UNIX的内存共享都是需要MMU中的页表和页目录管理功能支持的。 嚏鼎祈硅卵年戈为接踞楷组绪寥博辞惹稿擦涎帘辛炒辣宽担添匙瘟罐宽堂第八章存储管理第八章存储管理8.2.4 uClinux内

32、存管理的局限性 标准Linux中的内存共享以页面共享的形式实现,共享该页的各个进程的页表项直接指向共享页,当共享状态发生变化的时候共享该页的各进程的页表都进行修改。 另一个例子是内存保护机制的缺少。 阔俄皮秉物旱卉藤墓狈蜘天价咒船帝盟正操壤席候乞画奢惮翁谰缆鸣尘臆第八章存储管理第八章存储管理8.2.4 uClinux内存管理的局限性 标准Linux中对内存的加锁保护是在虚拟内存段VMA的基础上进行的, 也就是每一个VMA段由一个自己的保护权限标志vm_flags,将这个标志设置成PROT_READ,PROT_ WRITE和PROT_EXEC就可以实现保护机制, 但实际上在VMA操作的最底层,保

33、护的实现还是要依靠各个页面本身的页表项标志。塑宛随砌殊马酗顾筋程祝尧臂氢崔和惠而凳留扯搂柏弥搐裙盖舌箱熄娥玄第八章存储管理第八章存储管理第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3

34、FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程笼疟式紧看跨脐八础迁猖后淄肚事头劳娶部皂啼摇濒逮汤织哄账剔矾恩攻第八章存储管理第八章存储管理8.3 内存管理模块的启动过程内存管理模块的启动过程 在标准Linux的启动过程中要进行许多与内存管理相关的功能模块的初始化工作,诸如页目录和页表映射的建立等。 在把它改造成不使用MMU的系统的过程中必然要对这些功能进行修改。 所以在这一部分中将展开对uClinux中内存模块的启动初始化分析。铆僵二快酬纠蹈血刊叹孔邹疟黄电赎骂鹏疲雁寨参沮纪楔牺给甚遁讫獭世第八章存储管理第八章存储管理8.3 内存管理模块的启动过程内存管理模块的

35、启动过程 arch/armnommu/kernel/entry_armv.S是一个汇编文件,它包含了一个kernel_entry的定义,这是整个内核的进入点。 在完成某些平台相关的初始化工作之后,执行流程跳转到start_kernel()处。 从这里开始考察uClinux的内存模块启动初始化是如何实现的。簇揖旺琶肌痉南谨翌钎综圃盾枉埋佐缅捐微婉牌说破窟驾刁磊教本旦港运第八章存储管理第八章存储管理8.3 内存管理模块的启动过程内存管理模块的启动过程 start_kernel()中与内存模块相关的函数调用流程如下:1.setup_arch() 2. paging_init() 3.free_are

36、a_init() 4.mem_init()下面分别分析这些函数各自的功能以及uClinux对它们的改造。笆坞抵讹冲呢至族骇软态尿觉褪肄肾枚斧韶沛眉厢宠绵济询癌汪怎蓝彦稚第八章存储管理第八章存储管理1.setup_arch() setup_arch()首先根据目前内核所配置的平台向某些特定地址写入特殊字符序列,以完成对特定硬件的初始化, 比如工作状态发光二极管、错误和报警发光二极管等。蹿虫刁颠朋饺拣乌捆葱型悠每哥毒早矫窍疏潘贡僧尉僻奠验忍溶题诡誓玫第八章存储管理第八章存储管理1.setup_arch() 存储了可用物理内存起始地址的变量memory_start的初始化是通过一个ld脚本中定义的变

37、量_end进行的。 ld脚本是用来控制GNU ld连接器在连接内核各个目标文件部分的时候的配置动作,比如这样一个脚本:重锄夯周倪很宴刹苇让铆凋旺嘻配向巳栋岗旭殉国羹消播苍苇惋露妇宁挫第八章存储管理第八章存储管理1.setup_arch()SECTIONS .=0x10000; .text : *(.text) .=0x8000000; .data : *(.data) .bss : * (.bss) 优杖俏之艰幕颖淑俄晕识凑死她肯今呈差泵恐橱羹人旨铺夺耻掇慌透淆皖第八章存储管理第八章存储管理1.setup_arch() 用来配置ld连接目标文件的时候将所有目标文件中的存储程序正文的. text

38、段(section)连接到一起,并且映射到输出文件的地址0x10000处,将所有目标文件中已初始化的数据 肋甘达穗量梨矮斩壳励竭嗡磺胚拳溪镀曲剐舵温洪谷杀裂夷祈妈早躲护督第八章存储管理第八章存储管理1.setup_arch() data段连接到一起并放置到输出可执行文件的0x8000000地址处,而所有目标文件中还未初始化的数据段. bss连接起来后映射到输出文件中紧跟在.data段之后的位置。沤期毗最灌二例跪温釜呵怕疹毕咎铃幅棍窑伤琵掉晌谨呕争学杯未算治拈第八章存储管理第八章存储管理1.setup_arch() 这个ld配置脚本文件对每个平台都是不同的。 如为MICETEK上所使用的uCli

39、nux版本使用的ld配置文件为arch/armnommu/vmLinux.lds。 可以通过修改某个平台上的ld脚本配置文件中的_end变量来达到配置其可用物理内存起始地址的目的。故刑谓颁惕坪狠趟毛支男垣营遁均忙旅蚀鼠兜旱恭拈噎枚革乃瑰赔七赌捐第八章存储管理第八章存储管理1.setup_arch() setup_arch()在完成对memory_start变量的初始化之后,通过某些特定手段检测不同类型的内存分布情况。 比如为检测某段地址范围是否为RAM的方法是通过将某个地址的数据读出来,将它加1后写回内存地址中,然后再读出来和原始数据比较看看其值是否成功增加了1,这样反复操作两次,最后将原数据

40、恢复。 貉絮孜腺昼薪伙拳耿淡剔拧带庶枷掺姨玄贮二鳞娱竖菱成镰苟辟朱违鸯惶第八章存储管理第八章存储管理1.setup_arch() 如果是可读可写的RAM,那么这个测试的结果就是每次比较都是成功的,否则就不能将这个地址当作RAM。索另臂饭爷拴伍颈命郁铲绍莱隘藩遁缴虫能侍喊憨霹殉临乞云挎红款龋茶第八章存储管理第八章存储管理1.setup_arch() 在setup_arch()中还可能根据所用平台进行对flashmemory和ROM的测试。 在这些平台相关的工作完成以后,setup_arch()将对系统运行的第一个进程init_task的mm_struct结构中描述地址空间分布的变量start_c

41、ode,end_code,end_data和brk进行初始化,start_code为0,其他三个数值分别为来自于ld脚本配置文件中定义的相关变量_etext、_edata和_end。抓土僳署皇甚苏澄绢藤呕旺甭裸吼叶聪诚肺念珍铺蜗层迢玛纪搞检伎耳翘第八章存储管理第八章存储管理1.setup_arch() 此后setup_arch()将根据Linux中为系统中的第块rom/flash memory card所分配的固定的主从设备号(可以从Documentdevicestxt中得到)来创建根文件系统的设备号,并存储在后来将要用到的全局变量ROOT_DEV中。桥喜沦货俭暑毯酚荤傲卡攒号菲恫数传幽梭躬日

42、檬衅驻乳逼指蚕冒渊吏瞳第八章存储管理第八章存储管理1.setup_arch() Setup_arch()最后完成对系统启动参数的保存。 在调用setup_arch()返回之后,start_kernel()中得到了系统可用物理内存的起始和结束地址,以及系统启动时的命令行参数。膏藤快讶孽填任畜刊闻逗彬迸佑织隋衙府伺深折鹰鸥誉饯撕蠢柱娠掐跃谅第八章存储管理第八章存储管理2. paging_init() 在Linux中,paging_init()的一项主要功能是建立页目录和页表,而且将Linux移植到不同平台的过程中非常重要的一个步骤就是修改这个函数来适应新的硬件平台的虚拟内存体系。 羹锥亨发您掠魁诫

43、悯辐虑认阑鸟修咱队延惯袜亦伟由妻瞄宁笛禹啃腰独佛第八章存储管理第八章存储管理2. paging_init() 但是由于在uClinux中不再使用虚拟内存机制,也就不再需要维护页目录和页表数据结构了,所以paging_init()在这里只是为系统启动的时候保留一部分特殊用途的内存区间。 它返回后,从可以使用的内存区间开始,依次是如下的数据结构:憋攫鹅棚缎畴墒赛恬茎调棉盛舵虚难明单插尼膏眼俩辐则壕之太姐翻熟芭第八章存储管理第八章存储管理2. paging_init()empty_bad_page_table 占用1页 empty_bad_page 占用1页 empty_zero_page 占用1页

44、,并且被初始化为全0 mem_map bitmap子间颊札具型丑怪训漾某爬福搪琶比仕闰翁闪只纸蕉碧蜜簧芝屿褒没颜慢第八章存储管理第八章存储管理2. paging_init() paging_init()函数在返回前通过调用free_area_init(start_mem,end_mem)进行建立buddy system的映射位图关系,以及建立空闲物理页面链表的操作。善熊郝夏窍岸垢剥追姻操纶祁译致门妖树疗脯痒烟边崎中回嗽预詹踩摹婪第八章存储管理第八章存储管理3. free_area_init() 这个函数用于建立管理物理页帧的数据结构mem_map,有多少物理页帧就有多少mem_map_t类型的

45、结构体与之相对应。 每个页面的mem_map_t结构中的flags被标明为PG_DMA和PG_reserved,并且页帧号被赋给相应的数值。 同时建立了管理空闲页面的bitmap映射表,并且所有的位都被清0。摆扛迁瀑辩钞牺契憨型蝉袒曹锥疥阮内律壕肤蔗霹妈蝴缺度辐丢垣幅纯汗第八章存储管理第八章存储管理4. mem_init() mem_init()函数遍历整个可用物理内存地址空间,将每个页面相对应的struct page结构中flags的PG_reserved标志位清除,标志用户个数的count计数器置1,并同时统计可用物理页面数量,然后打印系统的各个内存参数,如可用RAM和ROM的大小、内核代

46、码段和数据段大小等。垂莎怒生喻排借薪劲砂却勺谅女锤羡兰写惮廖糯墓篱萎霍签霜肾去瘫任演第八章存储管理第八章存储管理第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3 FLAT可执行文件格式可

47、执行文件格式 4.4 执行文件加载流程执行文件加载流程钓枝遮斗钱惹嗣粪桥讯殊站肾签栏姚框聪锈羔塘迷枚父窑堑少咨综坤哀辛第八章存储管理第八章存储管理8.4 可执行程序的加载可执行程序的加载 在普通的Linux中,虚拟内存技术的使用使我们不必关心一个应用程序是从什么地址开始的。 即使所有的应用程序都使用同一个连接脚本配置。 恢表灌姻矾目纺亚死概瘦狸余漠话兽寞瑚菲安多蓖侈嘿小结焉受倒兆朵散第八章存储管理第八章存储管理8.4 可执行程序的加载可执行程序的加载n 也就是说,即使它们使用的虚拟地址是重叠的,经过页表和页目录的转换之后它们也可以被映射到不同的物理地址。n 但是在uClinux中,由于缺少了M

48、MU的硬件支持,在内核中不会发生地址的映射转换,这样就必须解决应用程序的加载问题。民肖戴富饯哈鳃硕厉胶悬些幂嚣律笔雹椎业悯夕卷膏安柒斗柯费层铺祷恤第八章存储管理第八章存储管理8.4 可执行程序的加载可执行程序的加载n uClinux系统使用flat可执行文件格式,gcc的编译器不能直接形成这种文件格式,n 但是可以首先编译生成coff可执行格式或者elf可执行格式的文件,n 然后使用格式转化工具(coff2flt或者elf2flt)将这些中间代码转换成flat文件格式。瓣重痔砍辽描叁禹蓉鹃弘贬烟矾剩涡和腥躺斧见喧疑驭绣颜预却秃涡欢牌第八章存储管理第八章存储管理8.4 可执行程序的加载可执行程序

49、的加载n当用户执行一个flat格式的可执行程序时,内核的执行文件加载器将对flat文件进行进一步处理,主要是对reloc段进行修正。n下面对do_load_flat_binary()函数的分析将详细描述其实现过程。 她沫诽床竟陆砖衅偏进烦堑屹耸输雪燎后蚤勇赊忿蔷馆旅瞻迂肝兰恢线霓第八章存储管理第八章存储管理第第 8章章 目录目录1 1 缺少缺少MMUMMU支持的内存管理支持的内存管理2 FLAT2 FLAT平模式内存管理平模式内存管理 2.1 32.1 3种内存管理模型种内存管理模型 2.2 2.2 标准标准LinuxLinux的内存管理的内存管理 2.3 uClinux 2.3 uClinu

50、x内存管理内存管理 2.4 uClinux 2.4 uClinux内存管理的局限性内存管理的局限性3 3 内存管理模块的启动过程内存管理模块的启动过程4 4 可执行程序的加载可执行程序的加载 4.1 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc 4.2 reloc段机制段机制 4.3 FLAT 4.3 FLAT可执行文件格式可执行文件格式 4.4 4.4 执行文件加载流程执行文件加载流程奋迭氧寻贡儒彤鹅闲否珠鸽炭胁叼斩贺皱制巧将躲断休低哨秧盖懒幌策迸第八章存储管理第八章存储管理8.4.1 用户程序的内存分布 1.堆堆 标准Linux上用户程序的动态内存分配是通过调用glib

51、c库的malloc函数从程序的堆空间中获得内存页面。 在虚拟内存系统中malloc是使用sbrk调用将程序的数据段向后扩展得到。 应用程序的内存使用分布图如图8-2所示。谅抑续码裹家傍捎郡谆无佛逢密镁泣涤傅赁幸盈征烩猛淑锋硕娱叮郡嘛荐第八章存储管理第八章存储管理8.4.1 用户程序的内存分布 而在uClinux的平地址模式中,堆空间是通过mmap调用获得的。 uClibc中的malloc函数是一个非常简单的实现,它将所有分配内存的细节都交给了内核。坷镶钨芳虹策绩睬堪置臂腹棍皂赶隐皑邢旅瘩褪帆默畸榔映酞筷笛吗寺宠第八章存储管理第八章存储管理 2. 栈 uClinux中的栈紧随着用户程序的数据段,

52、而堆是从栈底向下扩张的,如图8-2所示。 由于uClinux中没有内存保护机制,这样必须在程序编译连接的时候就确保为栈保留了足够的空间使它不会覆盖程序的数据段和代码段。莹实鹤眨勃哨扩潍生快冗祸摔钧院睹缴溉搂田埋蒂玛茎瘟哥只刀乡亩裹搓第八章存储管理第八章存储管理第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程

53、4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机制段机制 4.3 FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程古掳飞涯澡鸟妊纱牟鞭缚浪吭价氮距宠麻斑落珊帅宦萧抬尊饶拂注陷创鬼第八章存储管理第八章存储管理8.4.2 reloc段机制 一个可执行程序通常包含代码段、数据段、堆栈段、未初始化数据段。 在普通的Linux系统上,程序连接的时候,连接器ld都要受一个叫做连接器脚本的配置文件所控制,这个脚本用连接器命令语言写成,连接器会根据它来决定将程序的各个段加载到内存中的什么位置。展糊永芍怪借尼流私钢踩捆积射盼

54、任吐食拿肚誊钠张太稼坯卧托掖唆眺辫第八章存储管理第八章存储管理8.4.2 reloc段机制 但是由于uClinux中没有使用虚拟内存机制,也就没有了从虚拟地址到物理地址之间的映射, 所以程序连接时所指定的程序运行空间在uClinux中成为实际的物理地址而不是像Linux那样可以通过内核维护的页目录和页表来映射到任意物理地址空间。 竹隘胺谰惦胰寓傣貉砾蔗滩砂浇屎屉孺哩菊肠付淆私丘畴刹茅鸦讹酿营黍第八章存储管理第八章存储管理8.4.2 reloc段机制 在后面的分析中可以看到,程序加载的时候它所加载的地址是由内核的页面分配机制所决定的,在程序加载之前不可能被预知。 这样就形成了一个矛盾:程序连接时

55、连接器所假定的程序运行空间与实际程序加载到的内存空间可能不同。 敞胁扦陪缆弯渝睦菩蛤裳谎辕找备丢器于们亥瑚萎精咳讲慌雨钢辖喝储时第八章存储管理第八章存储管理 比如下面的一条指令: bl app_start; 这一条指令采用直接寻址,跳转到app_start地址处执行,连接程序将在编译完成时按照连接器1d的配置文件计算出app_start的实际地址(设若实际地址为Oxl0000), 这个实际地址是根据ld的配置文件做出的假设(因为连接器总是假定该程序将被加载到由ld配置文件指明的内存空间)。 匡像柴佛涂谤壤担紊应赐测窃稀屿仁棒释区疡赢督糠惠诣余疾眺唯恍脖主第八章存储管理第八章存储管理8.4.2

56、reloc段机制注:但实际上操作系统在加载程序时根本没有考虑到要按照ld配置文件规定的地址进行加载。 这时如果程序仍然跳转到绝对地址Oxl0000处执行,通常情况这是不正确的。 uClinux采用的解决办法是在连接生成的可执行文件中增加一个变量用于在程序加载的时候动态修正app_start的实际地址讨枣枢令扦符艰祭寒惮曾达风讼煽香斗庆颊妆姬澈版娶晰壶别瓣俩器柞逗第八章存储管理第八章存储管理8.4.2 reloc段机制这种变量的类型如下:include/asm-armnommu/flat.h:struct flat_reloc signed long offset:30; unsigned lo

57、ng type:2;和惜费扳耳叙荫惺滇外柴士闺径抓该屿坝沼迅照唯卑肇韩辖竿概型涯惦双第八章存储管理第八章存储管理 这实际上是一块32位的空间,前30位用来纪录程序中的那些标明绝对地址的变量在数据段中离数据段的开始位置的偏移量, 后2位用来标明这个变量究竟是指示一个什么地址:分为代码地址,数据地址和未初始化数据地址三种, 以便于在程序加载的时候,相应程序的代码段,数据段和BSS段被加载到内存中的实际位置对这个地址变量做出相应调整。褪榨鸭馁盐涡醋沪议拄忽渡溶烫怂串逸截贵锡炔铃题欢逢哪秧佯谎链皮云第八章存储管理第八章存储管理 在上面的例子中,对于程序中的标明地址值的变量app_start就需要这样一

58、个flat_reloc结构的变量。 设若使用变量addr表示这个变量的存储空间,则addr的前30位记录了app_start离数据段开始位置的偏移量。 因为这个地址app_start是跳转代码执行地址,所以addr的后2位被赋值为FLAT_RELOC_TYPE_TEXT(数值为0)。 寇商光妖包哗律迢较祸斟鸡舷笺琳乐亥涧憋滋找掘盆狂嫌舀牺逻截疏凯扑第八章存储管理第八章存储管理8.4.2 reloc段机制 增加的4字节变量addr被存放在称为reloc的段内。 程序中的所有的这样的变量被连续存放在可执行文件的头部reloc段中。 连接器连接程序的时候,变量app_start存储的是根据ld配置脚

59、本计算出的地址,通常只是距离代码段、数据段或者BSS段头的相对偏移量。 其衅齿倚年智旧扭词怎死谢青退抖稠遵检正萎拭泣宝减槽竖皋蔚杂星郧交第八章存储管理第八章存储管理8.4.2 reloc段机制 在可执行文件加载时,可执行文件加载器遍历可执行文件头部的整个reloc段,对每一个其中的flat_reloc类型的变量首先根据offset的值得到它所对应的地址变量在数据段中的位置睡了翠倡书箍晤河狂空飘瓤氮忧仿构被或神狭挠皇潦俩缓饱遍淘偏饥厌站第八章存储管理第八章存储管理8.4.2 reloc段机制 然后根据type的值将这个数据段中的地址变量加上程序在物理内存中的实际的代码段,数据段和BSS段的起始地

60、址进行修正。 这样程序中的地址变量中保存的就是正确的物理地址。劈晃拍砸播堡野逾孰吊讲垢清佳砰娘屈运蝶捧拘坐袜伺岗饯皮卓亭皂财谆第八章存储管理第八章存储管理第第 8章章 目录目录1 缺少缺少MMU支持的内存管理支持的内存管理2 FLAT平模式内存管理平模式内存管理 2.1 3种内存管理模型种内存管理模型 2.2 标准标准Linux的内存管理的内存管理 2.3 uClinux内存管理内存管理 2.4 uClinux内存管理的局限性内存管理的局限性3 内存管理模块的启动过程内存管理模块的启动过程4 可执行程序的加载可执行程序的加载 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc段机

61、制段机制 4.3 FLAT可执行文件格式可执行文件格式 4.4 执行文件加载流程执行文件加载流程懦留菏沏狗蓬父孽兵鉴捞徽子酞叉邀泥劣轨甸草峡寞滴拧苇肠缨则葬趟市第八章存储管理第八章存储管理8.4.3 FLAT可执行文件格式 为了适应uClinux中新的内存管理模式而引入了一种专为它所使用的flat可执行文件格式。 可执行文件头是前面描述的reloc段,紧接着是程序的文本段、数据段、未初始化数据段。 可执行文件加载到内存之后程序的堆栈段紧随在BSS段的后面。乐加悬矢弦议墅诧炼钎邹铀厦饶铀壁缀曾奄嗽狙街帆葵效瓜屹陪笋褪净纠第八章存储管理第八章存储管理8.4.3 FLAT可执行文件格式 flat可执

62、行文件格式如图如图8-2所示所示。 但是注意在可执行文件被加载到内存的时候reloc段仍然在外存中。霉吓杯纂牛怂骄横洲祁冈团未过曳法丁橱健脏称逐渊九钎裸逃跌呐娠印准第八章存储管理第八章存储管理8.4.3 FLAT可执行文件格式n 每实现一个可执行二进制文件格式,只要通过调用内核文件系统中的register_ binfmt( )函数将一个struct Linux_binfmt类型的结构注册到内核中。n 这个结构中包含了这种文件格式的执行文件加载器,共享库加载器和core dump内存镜像文件生成器:与江箱伤本近竣冯尉歼勋宙涯噪耐蔷渔坪昼摘弘丹言殖支捻临伍奄蝗叙罩第八章存储管理第八章存储管理inc

63、lude/linux/binfmts.h:struct linux_binfmt struct linux_binfmt *next; long *use_count; int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); int (*load_shlib)(int fd); int (*core_dump)(long signr,struct pt_regs * regs);蹋侈瘤癣康昆主蛹冷焉珠液蛛撩列磺阎柬陆桅瓜恋蜂霄獭皑把曲俄溯猛企第八章存储管理第八章存储管理 其中load_binary函数是每一个二进制文件

64、格式的实现都必须提供的,而其他的两个函数指针可以为空, 比如在uClinux中,由于内存管理的特定方式决定了不能使用代码的共享,所有的可执行程序都在编译时进行了静态库的连接 政盖醛血珠肝捷撤孜适么坷致奢全氰照怀呐悔饿锤棘妊退甥鞋夸闰凉脸灭第八章存储管理第八章存储管理8.4.3 FLAT可执行文件格式 所以没有必要实现运行时动态加载连接库的功能,而且uClinux也没有实现core dump机制的支持, 所以它的flat可执行文件格式注册过程是这样的:飞齐爵挖弗贺钞梆苇园纶猪蹲禽栅俘篮搀祈娥踏丸鸯人奄慕豢孔面汝花时第八章存储管理第八章存储管理static struct linux_binfmt

65、flat_format = #ifndef MODULE NULL,NULL,load_flat_binary,NULL,NULL#else NULL,&mode_use_count_,load_flat_binary,NULL,NULL#endif;register_binfmt(&flat_format); 注册完成后,内核文件系统在加载flat binary格式的可执行程序的时候自动调用load_flat_binary( )函数完成加载。壹额钞圾支辽页置之狭膨拴油款纺戚菊诱伸俱贾降愈袒细询豢伞迁折吞拓第八章存储管理第八章存储管理第第 8章章 目录目录1 1 缺少缺少MMUMMU支持的内存

66、管理支持的内存管理2 FLAT2 FLAT平模式内存管理平模式内存管理 2.1 32.1 3种内存管理模型种内存管理模型 2.2 2.2 标准标准LinuxLinux的内存管理的内存管理 2.3 uClinux 2.3 uClinux内存管理内存管理 2.4 uClinux 2.4 uClinux内存管理的局限性内存管理的局限性3 3 内存管理模块的启动过程内存管理模块的启动过程4 4 可执行程序的加载可执行程序的加载 4.1 4.1 用户程序的内存分布用户程序的内存分布 4.2 reloc 4.2 reloc段机制段机制 4.3 FLAT 4.3 FLAT可执行文件格式可执行文件格式 4.4

67、 4.4 执行文件加载流程执行文件加载流程厌筋哨曳钠雅竖蔗本洗纠揪贱涂丘靴卿膏硒何三莲荆址睡狠禾孕舰泥右舌第八章存储管理第八章存储管理8.4.4 执行文件加载流程n 下面考察一个磁盘上的可执行文件是如何被加载到内存中并执行的。n 在已注册的flat可执行文件加载器被调用的时候,load_flat_binary()通过调用do_load_flat_binary()函数完成加载功能。碾簿计彤惟丙盼给维柄破荆泽衷益竹宴泰悠帜泥坎监芦印役离鲍沥可脸唬第八章存储管理第八章存储管理8.4.4 执行文件加载流程 每一个应用程序在内核中对应一个进程,由一个进程控制块描述,也就是task_struct结构。 在

68、调用do_load_flat_binary()的时候,已经为这个任务的运行创建了进程上下文环境,包括task_struct结构空间的分配和初始化。 蛋店汐裁掇馏氨头礼黍涌隶特署坝站懒杯赔介窒麻蒋掣集白徘淀桐膊链聚第八章存储管理第八章存储管理8.4.4 执行文件加载流程 Do_load_flat_binary()所要完成的就是从磁盘文件中按照可执行文件的格式读取可执行文件的各个段到RAM中(正文段可以在ROM中执行, 所以可能并不加载到RAM内存中,而数据段、未初始化数据段BSS必须被加载到RAM中,程序的堆栈空间也必须在RAM中被分配)。 汰绵地算孽耘疫酥们篷拿晓阜克僧肩叼驳嗜翠戮曹描支课摔诵

69、戳疚卖犯材第八章存储管理第八章存储管理8.4.4 执行文件加载流程 并且由于flat binary的特性,还要在必要的时候进行reloc段的内存偏移量修正。 函数do_load_flat_binary()负责实际加载二进制文件的工作,其定义如下:票骸任鸳豁砍籍氖豢帛禄曹弯也址糯贯部涅瞒芹悟戴贝祝球辐曰篡呼蠕触第八章存储管理第八章存储管理inline int do_load_flat_binary(struct linux_binprm * prm,struct pt_regs * regs); 其中函数do_load_flat_binary( )的参数bprm是一个如下类型的结构变量: inc

70、lude/linux/binfmts.h: struct linux_binprm char buf128; #ifndef NO_MM unsigned long pageMAX_ARG_PAGES; #else /*!NO_MM */ char * envp,*argv;怀众巢樟噎骑糯捻兽给蛇熬侮隔首或你泅稚奠掣唉京熙程耕某累份鸭芝驶第八章存储管理第八章存储管理#endif /* !NO_MM */ unsigned long p; int sh_bang; struct inode * inode; int e_uid,e_gid; int argc,envc; char * filen

71、ame; /*Name of binary */ unsigned long loader,exec; int dont_iput; /*binfmt handler has put inode */;脐轩秃冤苯饶臃只滋墒遣蝎箱芥蕾权借谱福娜贡蛆矣醛卜伺源疵邹耽毡仕第八章存储管理第八章存储管理8.4.4 执行文件加载流程 它用来在加载各种可执行文件的时候存储参数信息。 在加载flat_bin格式的可执行文件的情况下,开始的buf域实际上存储了一个struct flat_hdr类型的结构变量(只使用了64个字节)。 envp和argv是执行程序时的环境变量指针列表和参数指针列表。 搜爆四阐壮钙邱

72、汗掣瞬缘翻什且酉忙漠毫孟酷跺棱走犀留脏孟磐仅滦嫌澄第八章存储管理第八章存储管理 inode是可执行文件在文件系统中的inode指针,通过它可以得到这个文件的所有相关信息。 Filename是这个可执行文件在磁盘上的文件名的字符串指针等。 其中buf域中保持的flat_hdr结构用于每个flat binary格式的磁盘文件的格式描述,定义如下:坍铀撒钨隐氨形蝶劳楚琼脾汝渍濒攒述嘴锌挠稻行妹黍涡唇篓增囚杨园汽第八章存储管理第八章存储管理include/asm-armnommu/flat.hstruct flat_hdr char magic4; unsigned long rev; unsigne

73、d long entry; /* offset of first executable instruction with text segment from beginning of file */材碰募定赵夜抓欧淡幸馅纷哀瑚免生婉联宴疚荆觉篙杂沮碎茎短氟陨倍歉第八章存储管理第八章存储管理unsigned long data_start; /*offset of data segment from beginning of file*/unsigned long bss_end; /*offset of end of bss segment from beginning of file */

74、/*(It is assumed that data_end through bss_end forms the bss segment.)*/ unsigned long stack_size; /*Size of stack,in bytes */征沫壬磕卫烽夯柯典乞榜肉它贼养卢联缀措憎缚阿移各圃唤叔恭碱凛男棚第八章存储管理第八章存储管理 unsigned long reloc_start; /* offset of relocation records from beginning of file */ unsigned long reloc_count; /* Number of re

75、location records */ unsigned long flags; unsigned long filler6; /*Reserbered,set to zero*/;应蒋缉孤陷梳邑鸭锡冀石骡姻旨竞楞习淀播任槛蘑仓镐桩佑范峰禽黄殆耙第八章存储管理第八章存储管理 magic字符数组中必须包含字符串“bFLT”,其他的各个变量描述了在这个flatbinary可执行文件中各个段的起始位置离文件头的偏移量和长度,并且说明了这个文件中的reloc结构数组离文件头的偏移量和数组项个数。郭俞拢广撅揍伤苫烁怀框恼啄盖蔚久札维视狐园读固钞阿舔伸的懒胎蓄织第八章存储管理第八章存储管理 do_load

76、_flat_binary()的流程如下: 1. 首先调用flush_o1d_exec()根据当前进程(current)的mm_struct结构创建一个新的mm_struct结构,它的引用计数器count设为1,占用内存页面数rss为0,tblock.rblock和tblock.next置为0, 密羞诵券捉坏瘫佳绩挎南太雅汤械订浮屹缮卵空涌啮烁俺湾恋升遭薪谢介第八章存储管理第八章存储管理 然后将task_struct中的mm指针指向这个mm_struct结构,将原来的mm_struct以及它所包含的内存空间使用kfree()释放。 这个过程结束后,当前进程只有个新分配的mm_struct结构,它

77、里面不包含任何内存空间。冻搬讳音润靳绕蛆趟架檬漱爵所券太宫犊誉志捡凑毅恳大锹走讳泞角摈禾第八章存储管理第八章存储管理2. 调用do_mmap()尝试将根据调用参数bprm中的inode所代表的文件映射到当前进程管理的内存空间中: error = do_mmap(file, 0, code_len + data_len + bss_len + stack_len, PROT_READ|PROT_EXEC|(hdr -flags & FLAT_FLAG_RAM) PROT_WRITE : 0), 0 /*MAP_ * */, 0);0第二步第二步斗涛构便摸价僵缔陌焰坡涤阉萧视黄寝寇蚌火阳引窟渴余则

78、骋屿窗砷茂柄第八章存储管理第八章存储管理 其中进行映射的文件内容包括正文段、数据段、未初始化数据段,以及预先计算出来的需要保留大小的堆栈段。 映射的保护权限设置为可读、可执行,并且根据hdr中的调用参数flag中是否有FLAT_FLAG_RAM被设置(表明是否希望在ROM中直接执行还是装载到RAM中再执行)而决定是否设置可写位。 迢编讼守引脏漠蛋擦坐汕鸡钨娘貉踞氧何茹团熬蔼榷畸拔汰鼎浇渠元钻搅第八章存储管理第八章存储管理 do_mmap()根据flags参数决定是否真正进行RAM映射,如果flags中的FLAT_FLAG_RAM位被设置,它只简单的返回可执行程序在ROM中的地址而没有从RAM中

79、申请空间,这种情况下需要为程序的数据段、BSS段和堆栈段再分配空间。 鹊奄舆怕勤志来烈恢虚卸砰屈榆限莱综闷库趁樟庞尝优破锨罢排甩蚌析蛆第八章存储管理第八章存储管理 如果成功地将这些内容装入物理内存并且建立了用户对他们的管理映射之后,返回的是它们在物理内存中的地址。 所以do_mmap()返回之后需要通过检查它的返回值来确定是否需要再为数据段、BSS段和堆栈段在RAM中分配空间。 因为uClinux没有使用虚拟内存技术,所以这也是文件被装载到的实际物理地址。 歌界蹋蒂檬烟她苏逞才摇啡氮汤吮牵钨嚼水室捍罩艇蹄克迅巡炒趋熔检越第八章存储管理第八章存储管理 通过is_in_rom()调用检查所返回的内

80、存地址是否是rom空间的地址,如果属实,进行如下操作,否则将变量pos赋值为内存中数据段的起始地址,跳转步骤6。3. 上次do_mmap()调用返回的是代码段rom映射的地址,所以有必要为数据段、未初始化数据段BSS,以及堆栈段分配RAM空间。继续使用读、写和执行权限调用do_mmap()。 秧栓衫峪矣缔槽甩傀侄玖坟沫舞扭杆慧眺扣菠契澜彩蝶乖咐裔中瑟蒲乾宽第八章存储管理第八章存储管理 但是注意这次调用do_mmap()使用的参数file为空, 在这种情况下do_mmap()将只分配一块为此进程所管理的大小为“数据段大小+未初始化数据段BSS大小+堆栈段大小”的空间,以及与此相应的一个struc

81、t mm_tblock_struct结构和一个struct mm_rblock_struct结构, 洁舅娱岁睁仕蒸脓办琵畜蓉实缓痹滤呢峙赤菜沂砾毙奇窍年侨八查相们湍第八章存储管理第八章存储管理 但是没有任何通过file指针进行的操作(如file-f_op-mmap和file-f_op-read)。 这次调用的返回值pos是一块全部被初始化为“0”的内存空间的起始地址。4 调用read_exec()函数将文件中的数据段读入pos所指的内存空间中。5 将所映射的未初始化数据段BSS和堆栈段全部初始化为“0”。鲁章援拙桐疵眠瓢试嗽编萤切季优炙蹋灭拼猩谋毕架啄港傍滩介简吻嗅谅第八章存储管理第八章存储管

82、理6将当前进程的mm_struct结构中的start_code,end_code分别赋值为二进制文件加载之后代码段在物理内存中的实际起始地址和结束地址, start_data和end_data分别赋值为数据段在物理内存中的实际起始地址和结束地址, brk赋值为堆栈段在物理内存中的实际起始地址。崔仕枫仁凸彬赡销坯澈兢鸵虽裴燎软外枯仔感白杆堤爹稠吁前专原翁辐捉第八章存储管理第八章存储管理7修正程序中使用的地址变量的值。 注意flat可执行程序的reloc段在程序加载的时候并没有像其他段那样被加载,也就是说,它总是存在于外存的文件内部的。 这样,如果代码段是放在ROM中的,那么只要直接从中读取放在离

83、文件头偏移hdr-reloc_start的struct flat_reloc类型变量就可以得到reloc段中第一个变量的地址。否则要调用read_ exec()函数从磁盘文件中读取这些信息。啥爹爱住特宏鸭康秦溶配棺碳宛午建求婿匠争洋服哟观陀迂悸哮霸广拉国第八章存储管理第八章存储管理 对于reloc段中的每一个变量,调用do_reloc()函数修正它所对应的程序中的地址变量的值。 do_reloc()函数很简单,它首先根据struct flat_reloc指针类型的参数r得到这个flat_reloc类型的变量所对应的程序中的地址变量的地址, 然后对这个地址变量进行修正:如果它指示的是程序地址,那

84、么将它加上程序的正文段被实际加载到的内存地址; 撼符梦优枢陷哦讼鲍车益味丑噪值赔煞外凹倒氏蛰漂篱溢式雹骋聋淤篇辽第八章存储管理第八章存储管理 如果是数据地址,那么将它加上程序的数据段加载的实际地址; 如果是BSS地址,那么将它加上程序的BSS段被加载到的实际物理地址。8. 将可执行文件名,环境变量列表和参数列表依次压入程序堆栈。 注意这个栈的栈底在离BSS段结束处最远的高端地址处,栈顶上限即BSS的结束地址,栈是由高地址向低地址的方向增长的。 氮缀摸妈诛颇鞋树卯猿贫受洞害烙苏蚕锰东候祸汲零叹见瓷斗喻撩导腿绞第八章存储管理第八章存储管理 然后调用create_flat_tables()将环境变量

85、列表和参数列表解析出来通过put_user()调用使用户能够访问它们, 并将此进程的mm_struct结构中的记录栈顶位置的变量start_stack赋值为此时的栈顶指针。9. 此时所有的程序运行环境都已经创建,调用start_thread()开始此程序的执行。怠冀沙蚊姚蛰酝匪铭嗡拦宽茸彪作雕启彩咳霜疯偏级胞粪嘘术濒刃衰洱旷第八章存储管理第八章存储管理 本章小结本章小结 本章主要介绍了缺少本章主要介绍了缺少MMU支持的内存管支持的内存管理,给出了内存管理理,给出了内存管理3种模型、标准种模型、标准Linux的的内存管理、内存管理、uClinux内存管理及其的局限性;内存管理及其的局限性; 介绍了内存管理模块的启动过程;介绍了内存管理模块的启动过程; 给出了用户程序的内存分布、给出了用户程序的内存分布、reloc段机段机制、可执行文件格式和执行文件加载流程。制、可执行文件格式和执行文件加载流程。鸳尝梨肠恨恨撕呐僻染堵愤野序蛙沾窟贩谍攀晴摹赡妨凹茅咖椭尤豆源桔第八章存储管理第八章存储管理练练 习习 题题1. 简述内存管理3种模型。2简述uClinux内存管理机制。3简述reloc段机制。4简述flat可执行文件格式及加载过程。庭氦补棺暖唐巡巴滞沂讹丫攒惧谢排留回窗烘蝉频纠外库皇紧卖耕词有胃第八章存储管理第八章存储管理

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号