当前位置:   article > 正文

Norlit OS —— 自制操作系统 第6章 内存管理_cpuid 80000001 bit 29

cpuid 80000001 bit 29

6  内存管理

6.1         内存管理

大家在日常开发的时候经常用到mallocfree函数。但是,在内核中,我们并没有mallocfree这两个函数。这该怎么办呢?

         答案是自己规划。我们先建立kernel/memory/memory.c,然后把cstart中的内存处理相关程序移动到memory.c

         为了保持内存使用的对齐,我们将所有可用的内存分组,最少为8字节一组,然后16字节……以此类推,最大可达2GB一组。内存中,我们用链表的形式,链表节点存放在空闲内存的前4字节的位置上。

         知道原理以后,代码其实很好写。

另外,笔者观赏了一下GCC生成的代码,感觉非常狗屎,memory_free函数笔者用汇编可以21行写出的代码,GCC用了38行,而且还是手工对C代码优化过后的。这38行中包含大量的内存操作。而笔者的代码完全没有进行过内存操作。设想这是一段核心代码(还真的是核心代码),这点小小的时间差距会累积成多大!malloc函数笔者用了16行,而GCC用了39行。这就体现了为什么大型工程中的核心代码都是汇编写的。在用汇编改写之后,最后的二进制文件减小了1.5KB。在NorlitOS最初的开发阶段中,我们会尽少使用汇编,但是之后的优化工程中,汇编是必不可少的。

u_addr* memoryBlocks[30]={EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,//0-7 Bytes

                         EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,//8-17 KBs

                         EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,EMPTY,//18-27 MBs

                         EMPTY,EMPTY};// 28-29 GBs

代码6.1.1数据结构(chapter6/a/kernel/memory/memory.c)

我们不管理4Bytes以下的内存,因为管理这些内存会给系统额外的开销。对于这些内存,我们简单地丢弃它们。不过,使用mallocfree功能永远也不会产生这些多余项。EMPTY被定义成了0xFFFFFFFF,但其实0xFFFFFFD0xFFFFFFFE也是可以的。超过4KB的内存实际上应该让分页机制管理了,但是在分页机制实现之前,我们先把实现容许的最大范围变成2^31次,也就是2GB

笔者修改了loader.asm,将cpuid.inc与之合并,并且加入了检测分页机制支持的功能。

CPUInit:

   pushfd                  ;储存EFLAGS

   mov    eax,[esp]       ;保存老的EFLAGS

   bts    dword[esp],21   ;更改EFLAGS.ID

   popfd                   ;设置EFLAGS

   pushfd                  ;保存新EFLAGS

   pop    ebx              ;EBX=EFLAGS

   cmp    eax,ebx          ;检查EFLAGS.ID有没有被成功更改

 

   je     .nocpuid

   

   mov    eax,0x80000000     ; CPU扩展信息

   cpuid

   cmp    eax,0x80000001

   xor   eax,eax

   jb     .nonx     ;不支持CPU扩展信息

   

   mov    eax,0x80000001

   cpuid

   xor   eax,eax

   bt    edx,20      ;Check NX

   adc   al,0

   shl   al,1

.nonx:

   push  eax

   

   mov    eax,0x7

   xor   ecx,ecx

   cpuid

   pop   eax

   bt    ebx,7    ;Check SMEP

   adc   al,0

   shl   al,1

   

   push  eax       ;Reserved  NX SMEP PSE-36 PAT PGE PAE PSE

   

   mov   eax,0x1

   cpuid

   pop   eax

   bt    edx,17      ;Check PSE-36

   adc   al,0

   shl   al,1

   

   bt    edx,16      ;Check PAT

   adc   al,0

   shl   ax,1

   

   bt    edx,13      ;Check PAT

   adc   ax,0

   shl   ax,1

   

   bt    edx,6    ;Check PAE

   adc   ax,0

   shl   ax,1

   

   bt    edx,3    ; CheckPSE

   adc   ax,0

   

   mov   [BootParamPhyAddr+ PGInfo],eax

   bt    eax,1

   jc     PagingOnPAE

   jmp    PagingOn

   

.nocpuid:

   mov    esi, STR_FAIL

   call   DispStrPM

   cli

hlt

代码6.1.2检测机能(chapter6/a/boot/loader.asm)

当然了,由于我们修改了0x500处的结构,别忘记同时修改loader.incstruct

FASTCALLstaticvoidmemory_block_free(u_addraddress, u_addr sizep, u8 bit){

    u_addr* ll=(u_addr*)address;

    u_addr** head=&memoryBlocks[bit-2];

    u_addr*entry=*head;

    u_addr**prev=head;

   for(;entry!=EMPTY;prev=(u_addr**)entry,entry=*prev){

      if(entry>ll){

          if(!(address&sizep

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号