MMU、ELF的加载、linux的启动

来源:互联网 发布:数据库系统基础 编辑:程序博客网 时间:2024/06/06 04:19

WORD版 下载

 

一、MMU的产生

      许多年以前,当人们还在使用DOS或是更古老的操作系统的时候,计算机的内存还非常小,一般都是以K为单位进行计算,相应的,当时的程序规模也不大,所以内存容量虽然小,但还是可以容纳当时的程序。但随着图形界面的兴起还用用户需求的不断增大,应用程序的规模也随之膨胀起来,终于一个难题出现在程序员的面前,那就是应用程序太大以至于内存容纳不下该程序,通常解决的办法是把程序分割成许多称为覆盖块(overlay)的片段。覆盖块0首先运行,结束时他将调用另一个覆盖块。虽然覆盖块的交换是由OS完成的,但是必须先由程序员把程序先进行分割,这是一个费时费力的工作,而且相当枯燥。人们必须找到更好的办法从根本上解决这个问题。不久人们找到了一个办法,这就是虚拟存储器(virtual memory).虚拟存储器的基本思想是程序,数据,堆栈的总的大小可以超过物理存储器的大小,操作系统把当前使用的部分保留在内存中,而把其他未被使用的部分保存在磁盘上比如对一个16MB的程序和一个内存只有4MB的机器,OS通过选择,可以决定各个时刻将哪4M的内容保留在内存中,并在需要时在内存和磁盘间交换程序片段,这样就可以把这个16M的程序运行在一个只具有4M内存机器上了。而这个16M的程序在运行前不必由程序员进行分割。


      任何时候,计算机上都存在一个程序能够产生的地址集合,我们称之为地址范围。这个范围的大小由CPU的位数决定,例如一个32位的CPU,它的地址范围是0~0xFFFFFFFF (4G)而对于一个64位的CPU,它的地址范围为0~0xFFFFFFFFFFFFFFFF(64T),这个范围就是我们的程序能够产生的地址范围,我们把这个地址范围称为虚拟地址空间,该空间中的某一个地址我们称之为虚拟地址。与虚拟地址空间和虚拟地址相对应的则是物理地址空间和物理地址,大多数时候我们的系统所具备的物理地址空间只是虚拟地址空间的一个子集,这里举一个最简单的例子直观地说明这两者,对于一台内存为256MB的32bit x86主机来说,它的虚拟地址空间范围是0~0xFFFFFFFF(4G),而物理地址空间范围是0x000000000~0x0FFFFFFF(256MB)。


      在没有使用虚拟存储器的机器上,虚拟地址被直接送到内存总线上,使具有相同地址的物理存储器被读写。而在使用了虚拟存储器的情况下,虚拟地址不是被直接送到内存地址总线上,而是送到内存管理单元——MMU(主角终于出现了)。他由一个或一组芯片组成,一般存在与协处理器中,其功能是把虚拟地址映射为物理地址。

 

二、MMU工作过程

      大多数使用虚拟存储器的系统都使用一种称为分页(paging)。虚拟地址空间划分成称为页(page)的单位,而相应的物理地址空间也被进行划分,单位是页框(frame).页和页框的大小必须相同。接下来配合图片我以一个例子说明页与页框之间在MMU的调度下是如何进行映射的:

      在这个例子中我们有一台可以生成16位地址的机器,它的虚拟地址范围从0x0000~0xFFFF(64K),而这台机器只有32K的物理地址,因此他可以运行64K的程序,但该程序不能一次性调入内存运行。这台机器必须有一个达到可以存放64K程序的外部存储器(例如磁盘或是FLASH)以保证程序片段在需要时可以被调用。在这个例子中,页的大小为4K,页框大小与页相同(这点是必须保证的,内存和外围存储器之间的传输总是以页为单位的),对应64K的虚拟地址和32K的物理存储器,他们分别包含了16个页和8个页框。


      我们先根据上图解释一下分页后要用到的几个术语,在上面我们已经接触了页和页框,上图中绿色部分是物理空间,其中每一格表示一个物理页框。橘黄色部分是虚拟空间,每一格表示一个页,它由两部分组成,分别是Frame Index(页框索引)和位p(present 存在位),Frame Index的意义很明显,它指出本页是往哪个物理页框进行映射的,位p的意义则是指出本页的映射是否有效,如上图,当某个页并没有被映射时(或称映射无效,Frame Index部分为X),该位为0,映射有效则该位为1。


    我们执行下面这些指令(本例子的指令不针对任何特定机型,都是伪指令)
例1:
    MOVE REG,0 //将0号地址的值传递进寄存器REG.
    虚拟地址0将被送往MMU,MMU看到该虚地址落在页0范围内(页0范围是0到4095),从上图我们看到页0所对应(映射)的页框为2(页框2的地址范围是8192到12287),因此MMU将该虚拟地址转化为物理地址8192,并把地址8192送到地址总线上。内存对MMU的映射一无所知,它只看到一个对地址8192的读请求并执行它。MMU从而把0到4096的虚拟地址映射到8192到12287的物理地址。


例2:
    MOVE REG,8192
    被转换为
    MOVE REG,24576
    因为虚拟地址8192在页2中,而页2被映射到页框6(物理地址从24576到28671)


例3:
    MOVE REG,20500
    被转换为
    MOVE REG,12308
    虚拟地址20500在虚页5(虚拟地址范围是20480到24575)距开头20个字节处,虚页5映射到页框3(页框3的地址范围是 12288到16383),于是被映射到物理地址12288+20=12308。


      通过适当的设置MMU,可以把16个虚页隐射到8个页框中的任何一个,但是这个方法并没有有效的解决虚拟地址空间比物理地址空间大的问题。从上图中我们可以看到,我们只有8个页框(物理地址),但我们有16个页(虚拟地址),所以我们只能把16个页中的8个进行有效的映射。我们看看例4会发生什么情况

      MOV REG,32780
      虚拟地址32780落在页8的范围内,从上图总我们看到页8没有被有效的进行映射(该页被打上X),这时又会发生什么?MMU注意到这个页没有被映射,于是通知CPU发生一个缺页故障(page fault.这种情况下操作系统必须处理这个页故障,它必须从8个物理页框中找到1个当前很少被使用的页框并把该页框的内容写入外围存储器(这个动作被称为page copy,随后把需要引用的页(例4中是页8)映射到刚才释放的页框中(这个动作称为修改映射关系),然后从新执行产生故障的指令(MOV REG,32780)。假设操作系统决定释放页框1,那么它将把虚页8装入物理地址的4-8K,并做两处修改:首先把标记虚页1未被映射(原来虚页1是被影射到页框1的),以使以后任何对虚拟地址4K到8K的访问都引起页故障而使操作系统做出适当的动作(这个动作正是我们现在在讨论的),其次他把虚页8对应的页框号由X变为1,因此重新执行MOV REG,32780时,MMU将把32780映射为4108。


      我们大致了解了MMU在我们的机器中扮演了什么角色以及它基本的工作内容是什么,下面我们将举例子说明它究竟是如何工作的(注意,本例中的MMU并无针对某种特定的机型,它是所有MMU工作的一个抽象)。


      首先明确一点,MMU的主要工作只有一个,就是把虚拟地址映射到物理地址。
我们已经知道,大多数使用虚拟存储器的系统都使用一种称为分页(paging)的技术,就象我们刚才所举的例子,虚拟地址空间被分成大小相同的一组页,每个页有一个用来标示它的页号(这个页号一般是它在该组中的索引,这点和C/C++中的数组相似)。在上面的例子中0~4K的页号为0,4~8K的页号为1,8~12K的页号为2,以此类推。而虚拟地址(注意:是一个确定的地址,不是一个空间)被MMU分为2个部分,第一部分是页号索引(page Index),第二部分则是相对该页首地址的偏移量(offset). 。我们还是以刚才那个16位机器结合下图进行一个实例说明,该实例中,虚拟地址8196被送进MMU,MMU把它映射成物理地址。16位的CPU总共能产生的地址范围是0~64K,按每页4K的大小计算,该空间必须被分成16个页。而我们的虚拟地址第一部分所能够表达的范围也必须等于16(这样才能索引到该页组中的每一个页),也就是说这个部分至少需要4个bit。一个页的大小是4K(4096),也就是说偏移部分必须使用12个bit来表示(2^12=4096,这样才能访问到一个页中的所有地址),8196的二进制码如下图所示:

      该地址的页号索引为0010(二进制码),既索引的页为页2,第二部分为000000000100(二进制),偏移量为4。页2中的页框号为6(页2映射在页框6,见上图),我们看到页框6的物理地址是24~28K。于是MMU计算出虚拟地址8196应该被映射成物理地址24580(页框首地址+偏移量=24576+4=24580)。同样的,若我们对虚拟地址1026进行读取,1026的二进制码为0000010000000010,page index="0000"=0,offset=010000000010=1026。页号为0,该页映射的页框号为2,页框2的物理地址范围是8192~12287,故MMU将虚拟地址1026映射为物理地址9218(页框首地址+偏移量=8192+1026=9218)。以上就是MMU的工作过程。

三、S3C24XX的MMU工作过程


    下面我们针对s3c2410的MMU(注1)进行讲解。
    S3c2410总共有4种内存映射方式,分别是:
    1.Fault (无映射)
    2.Coarse Page (粗表)
    3.Section (段)
    4.Fine Page (细表)
    我们以Section(段)进行说明。
    ARM920T是一个32bit的CPU,它的虚拟地址空间为2^32=4G。而在Section模式,这4G的虚拟空间被分成一个一个称为段(Section)的单位(与我们上面讲的页在本质上其实是一致的),每个段的长度是1M (而我们之前所使用的页的长度是4K)。4G的虚拟内存总共可以被分成4096个段(1M*4096=4G),因此我们必须用4096个描述符来对这组段进行描述,每个描述符占用4个Byte,故这组描述符的大小为16KB (4byte*4096),这4096个描述符构为一个表格,我们称其为Tralaton Table.

    上图是描述符的结构
    Section base address:段基地址(相当于页框号首地址)
    AP: 访问控制位AccessPermission
    Domain: 访问控制寄存器的索引。Domain与AP配合使用,对访问权限进行检查
    C:当C被置1时为write-through (WT)模式
    B: 当B被置1时为write-back (WB)模式(C,B两个位在同一时刻只能有一个被置1)
    下面是s3c2410内存映射后的一个示意图:

      我的s3c2410上配置的SDRSAM大小为64M,该SDRAM的物理地址范围是0x3000 0000~0x33FF FFFF(属于Bank 6),由于1个Section的大小是1M,所以该物理空间可以被分成64个物理段(页框).


      在Section模式下,送进MMU的虚拟地址(注1)被分为两部分(这点和我们上面举的例子是一样的),这两部分为 Descriptor Index(相当于上面例子的PageIndex)和 Offset,descript index长度为12bit(2^12=4096,从这个关系式你能看出什么?:)),Offset长度为20bit(2^20=1M,你又能看出什么?:)).观察一下一个描述符(Descriptor)中的Section BaseAddress部分,它长度为12 bit,里面的值是该虚拟段(页)映射成的物理段(页框)的物理地址前12bit,由于每一个物理段的长度都是1M,所以物理段首地址的后20bit总是为0x00000(每个Section都是以1M对齐),确定一个物理地址的方法是 物理页框基地址+虚拟地址中的偏移部分=Section BaseAddress<<20+Offset ,呵呵,可能你有点糊涂了,还是举一个实际例子说明吧。

      假设现在执行指令MOV REG, 0x30000012,虚拟地址的二进制码为0011000000000000 00000000 00010010,前12位是Descriptor Index= 00110000 0000=768,故在Translation Table里面找到第768号描述符,该描述的Section Base Address="0x0300",也就是说描述符所描述的虚拟段(页)所映射的物理段(页框)的首地址为0x3000 0000(物理段(页框)的基地址=SectionBase Address左移20bit=0x0300<<20=0x30000000),而Offset=00000000000000 00010010=0x12,故虚拟地址0x30000012映射成的物理地址=0x3000 0000+0x12=0x3000 0012(物理页框基地址+虚拟地址中的偏移)。你可能会问怎么这个虚拟地址和映射后的物理地址一样?这是由我们定义的映射规则所决定的。在这个例子中我们定义的映射规则是把虚拟地址映射成和他相等的物理地址。我们这样书写映射关系的代码:
void mem_mapping_linear(void)
{
    unsigned long descriptor_index, section_base, sdram_base, sdram_size;
    sdram_base=0x30000000;
    sdram_size=0x 4000000;
    for (section _base= sdram_base,descriptor_index = section_base>>20;
         section _base < sdram_base+sdram_size;
         descriptor_index+=1;section_base +=0x100000)
    {
         *(mmu_tlb_base +(descriptor_index)) = (section _base>>20) | MMU_OTHER_SECDESC;
    }
}


      上面的这段段代码把虚拟空间0x30000000~0x33FF FFFF映射到物理空间0x30000000~0x33FF FFFF,由于虚拟空间与物理空间空间相吻合,所以虚拟地址与他们各自对应的物理地址在值上是一致的。当初始完Translation Table之后,记得要把TranslationTable的首地址(第0号描述符的地址)加载进协处理器CP15Control Register2(2号控制寄存器),该控制寄存器的名称叫做Translation tablebase (TTB) register


      以上讨论的是descriptor中的Section Base Address以及虚拟地址和物理地址的映射关系,然而MMU还有一个重要的功能,那就是访问控制机制(Access Permission )。简单说访问控制机制就是CPU通过某种方法判断当前程序对内存的访问是否合法(是否有权限对该内存进行访问),如果当前的程序并没有权限对即将访问的内存区域进行操作,则CPU将引发一个异常,s3c2410称该异常为Permission fault,x86架构则把这种异常称之为通用保护异常(General Protection),什么情况会引起Permissionfault呢?比如处于User级别的程序要对一个System级别的内存区域进行写操作,这种操作是越权的,应该引起一个Permission fault,搞过x86架构的朋友应该听过保护模式(Protection Mode),保护模式就是基于这种思想进行工作的,于是我们也可以这么说:s3c2410的访问控制机制其实就是一种保护机制。那s3c2410的访问控制机制到底是由什么元素去参与完成的呢?它们间是怎么协调工作的呢?这些元素总共有:
    1.协处理器CP15中Control Register3:DOMAIN ACCESSCONTROL REGISTER
    2.段描述符中的AP位和Domain位
    3.协处理器CP15中Control Register1(控制寄存器1)中的S bit和R bit
    4.协处理器CP15中Control Register5(控制寄存器5)
    5.协处理器CP15中Control Register6(控制寄存器6)
    DOMAIN ACCESS CONTROL REGISTER 是访问控制寄存器,该寄存器有效位为32,被分成16个区域,每个区域由两个位组成,他们说明了当前内存的访问权限检查的级别,如下图所示:


      每区域可以填写的值有4个,分别为00,01,10,11(二进制),他们的意义如下所示:


    00:当前级别下,该内存区域不允许被访问,任何的访问都会引起一个domain fault
    01:当前级别下,该内存区域的访问必须配合该内存区域的段描述符中AP位进行权检查
    10:保留状态(我们最好不要填写该值,以免引起不能确定的问题)
    11:当前级别下,对该内存区域的访问都不进行权限检查。
      我们再来看看discriptor中的Domain区域,该区域总共有4个bit,里面的值是对DOMAIN ACCESSCONTROL REGISTER中16个区域的索引.而AP位配合S bit和A bit对当前描述符描述的内存区域被访问权限的说明,他们的配合关系如下图所示:


    AP位也是有四个值,我结合实例对其进行说明.
    在下面的例子中,我们的DOMAINACCESS CONTROL REGISTER都被初始化成0xFFFFBDCF,如下图所示:


例1:
Discriptor 中的domain=4,AP=10(这种情况下S bit ,A bit 被忽略)
假设现在我要对该描述符描述的内存区域进行访问:
由于domain=4,而DOMAIN ACCESS CONTROL REGISTER中field 4的值是01,系统会对该访问进行访问权限的检查。
假设当前CPU处于Supervisor模式下,则程序可以对该描述符描述的内存区域进行读写操作。
假设当前CPU处于User模式下,则程序可以对该描述符描述的内存进行读访问,若对其进行写操作则引起一个permission fault.

例2:
Discriptor 中的domain=0,AP=10(这种情况下S bit ,A bit 被忽略)
domain=0,而DOMAIN ACCESS CONTROLREGISTER中field 0的值是11,系统对任何内存区域的访问都不进行访问权限的检查。
由于统对任何内存区域的访问都不进行访问权限的检查,所以无论CPU处于合种模式下(Supervisor模式或是User模式),程序对该描述符描述的内存都可以顺利地进行读写操作

例3:Discriptor 中的domain=4,AP=11(这种情况下S bit ,A bit 被忽略)
由于domain=4,而DOMAIN ACCESS CONTROL REGISTER中field 4的值是01,系统会对该访问进行访问权限的检查。
由于AP=11,所以无论CPU处于合种模式下(Supervisor模式或是User模式),程序对该描述符描述的内存都可以顺利地进行读写操作

例4:
Discriptor 中的domain=4,AP=00, Sbit="0",A bit="0"
由于domain=4,而DOMAIN ACCESS CONTROL REGISTER中field 4的值是01,系统会对该访问进行访问权限的检查。
由于AP=00,S bit="0",A bit="0",所以无论CPU处于合种模式下(Supervisor模式或是User模式),程序对该描述符描述的内存都只能进行读操作,否则引起permission fault.
通过以上4个例子我们得出两个结论:
1.对某个内存区域的访问是否需要进行权限检查是由该内存区域的描述符中的Domain域决定的。
2
.某个内存区域的访问权限是由该内存区域的描述符中的AP位和协处理器CP15Control Register1(控制寄存器1)中的S bitR bit所决定的。

注:

CPU的地址线     MMU      RAM(DDR等)的地址线          NAND(NOR/硬盘)

1                           1                              1

2                           2                              2

3                           3                              3

…                          ..

                            16

31                                                         31

32                                                         32

                                                           4G*512=2T byte 的数据

 

MMU是把实际小的RAM放大了。

NAND里的程序在编译的时候是看RAM[A1] (如果有MMU虚拟,就是虚拟之后的,所谓每个程序有4G空间也就是这个意思)的,NAND只是个存储掉电不丢失的程序(只对本机的执行不考虑以后的对其他机子的编译来说是那些   对本机编译后的文件)的地方,程序执行的时候地址定义是在RAM里面的。 这些和分散加载(ARM)是一样的,在程序编译方面,都有“存放的地址”、“运行时的地址”,MMU先根据“存放的地址”找出程序,然后根据“运行时的地址”偏移加载到相应的MMU[x2] ,对应到CPU线中。另外还有bootloader和PC上的BIOS/主引导等的类似。    这样也是整个ARM、PC是统一的

 

  Linux运行起来后,模块的动态加载、应用程序手动命令执行(均使用ELF文件结构)和单片机(比如stm32)的静态编译(整体下来一个过程,没有前两者)是对应的(比如前两者调用内核的函数等,是内核里面仿照编译的过程给出了该函数的导出符合表,让前两者填上,从而对接上。是先下载好内核,运行时已经存在那,前两者再查找对接),只不过是挪了个地方。   此外在应用程序调用模块驱动方面使用了统一的接口(虚拟文件系统),linux内核又在模块驱动端做了链表性质的数据结构索引(udev、sysfile),这样应用程序和模块驱动对接在了一起。 

 

对从MMU<-------->内存<------------------>磁盘的注解:

“每个应用程序尊享4G空间[Microsoft3] ”,两个进程运行的虚拟地址可以重合,只是实际上操作系统给他们链接上了不同的物理内存地址。如图:

这些都是驻留在内核区的操作系统在控制编排的。联想ELF(包括内核和用户空间的)的加载:从实际存储地址(磁盘)到运行地址(内存),这个过程中,操作系统根据ELF(相当于windows的dll)的存储地址(可由文件地址根据文件系统索引到。而ELF的存储地址是编译时供JTAG等下载用的,JTAG把镜像下载到指定FLASH地址处);最后是MMU控制(这样的好处参见《ARM920T的MMU与Cache之虚拟内存管理------转载.pdf》),到CPU

32位系统中,每个应用程序享用4G空间是这个意思,其实际享用的物理地址空间是要操作系统分配的

 

 

 Linux的全貌,注解  应用程序ELF等的索引搬运加载(与上面的有关联)、驱动ELF加载、arm裸机分散加载、STM32启动加载过程:

 

Linux 下的bin目录是基本的程序集(主要是shell)。可以使用“P200 串口命令解析调用函数“的方法调用它们。     当Linux程序执行到从内核挂载文件系统时,就相当于P200的跑完外设初始化、开始启动执行实际应用程序一样(当然这个是固定的,缺少了进程、可安装的特点,但原理上一样的,都是在一个while(1)大循环当中,不管是linux还是uc/os II)。也相当于uc/os II中跑了下空闲程序,开始寻找被挂进程链上的程序;            同时一些“对应于安装好地址(这些地址被链表形式标记下来)的驱动的(当然因为有相对于静态编译的“编译机制的加载过程”,驱动也可以在运行时被加载)”应用程序在存储器中等待被调用(这些应用程序交叉编译好后被COPY静态放在FLASH中,调用入口是文件系统中的列出来的文件(通过一个文件路径在文件系统里可被索引到)。执行时从FLASH文件系统搬到RAM中,包括CODE区和DATA区,[x4] 该过程用到了编译链接的特征,用到了ELF---改地址特性(此有s3c2440裸机式的加载,也有linux操作系统干预的4G运行空间问题)。        加载完之后在文件系统中成的可执行程序文件,如/bin、/sbin,而/etc下的脚本是在这些可执行程序基础上写的类似于“P200串口命令解析调用函数“的解释性程序、中间又封装了几层直至实现了for/if等类似于C功能的高级解释性程序

 

    “从U-boot/前后台加载--àLinux内核”,就是从一个while(1)到另一个while(1),和“P200的bootloader、FW”是一样的,同时和“ windows下的 BIOS—>MBR[x5] (这之后还有可能有GRUB之类的)à操作系统自引导”是一样的

     从P200的角度看,ramdisk、system.img(即存放安卓java的文件)都属于应用,只是有层次差别。

摘自维基百科,注解windows的引导开启过程:

 

GRUB 第一版本

GRUB的步骤1包含在MBR中。由于受MBR的大小限制,步骤一所做的几乎只是装载GRUB的下一步骤(存放在硬盘的其它位置)。步骤1既可以直接装载步骤2,也可以装载步骤1.5:GRUB的步骤1.5包含在MBR后面的30千字节中。步骤1.5载入步骤2。

 

当步骤2启动后,它将呈现一个界面来让用户选择启动的操作系统。这步通常采用的是图形菜单的形式,如果图形方式不可用或者用户需要更高级的控制,可以使用GRUB的命令行提示,通过它,用户可以手工指定启动参数。GRUB还可以设置超时后自动从某一个内核启动。

 

当GRUB启动后

一旦选择了启动选项,GRUB把选择的内核载入内存并把控制交给内核。在此步骤中,对于Windows之类不支持多启动标准的操作系统,GRUB也可以通过链式启动[x6] 把控制传给其它启动器。在这种情况下,其它操作系统的启动程序被GRUB保存了下来;

 

 

 Linux环境变量与Windows中的作用是一样的

 

 

 

 

 

                                                


对于s3c2440裸机此说法正确。但对linux这类具有运行时加载的就不对了,应用程序的运行地址可以由操作系统在加载ELF时安排。

这个还需要看

 [Microsoft3]写程序的时候怎么享用还有疑问。

因为有操作系统的分配,在应用程序中,非法的地址应该不能被写入值。

比如*((int *)(0))=0x01;会异常的。 

不管怎么着只要一个程序块中的相对偏移正确,jump、goto指令能找到正确的地址就行。

 

 注意:应用程序属于文件系统的(比如yaffs),和busybox同属性,都是放在FLASH中,运行时再搬到RAM中,这时用到ELF编译机制特点的加载机制。而内核不同,其搭建好一般是不变的,相当于一个固定的大循环,所以其上电后只搬动一次地从FLASH到RAM,类似于ARM ADS1.2分散加载,但其的首地址可以任意换,还不知道这个的原因,虽然从对象化、状态机的智能化思维角度看很容易办到。

 

 Arm分散加载的部分很清楚,因为上电时程序从FLASH到RAM,只改一下偏移地址,DATA区类似也很好改。主要是改一次即可,后面程序都是按设定好的偏移按部就班的执行。

  STM32直接是下载到指定位置,程序就放在FLASH中执行,DATA区是改好了的,直接拷贝,更简单。那个开头的改FLASH向量的实际上是设置向量表寄存器的位置,好让程序找到向量表的地址;其FLASH的首地址和0x0是同一根线,通过BOOT线设置的,连在了一起, 所以这个地址偏移机制很简单,不需要从NAND到RAM的拷贝和设置)。

 

 但当有了MMU之后,这个就比较麻烦了。还不清楚;没有MMU的时候,TEXT区、DATA区可以按顺序存放即可,驱动与应用程序在执行时被加载可采用这种,也简单。

 

由于PC的商业格局,这成了约定俗成的。

由于分区的限制,使用了扩展分区。

以下摘自维基百科:

在MBR分区表中最多4个主分区或者3个主分区+1个扩展分区,也就是说扩展分区只能有一个,然后可以再细分为多个逻辑分区(每个逻辑分区有EBR,类似于MBR,逻辑驱动器的引导记录是链式的。每一个逻辑分区都有一个和MBR结构类似的扩展引导记录(EBR),其分区表的第一项指向该逻辑分区本身的引导扇区,第二项指向下一个逻辑驱动器的EBR,分区表第三、第四项没有用到。)

原创粉丝点击