GeekOS源代码学习(3)Main函数中Init_Mem初始化内存

这此来分析Main中的第三个函数Init_Mem(bootInfo)。

参数bootInfo是在主函数Main中传入的,为struct Boot_Info类型

定义在./include/geekos/bootinfo.h

struct Boot_Info {
    int bootInfoSize;    /* size of this struct; for versioning */
    int memSizeKB;       /* number of KB, as reported by int 15h */
};

内存信息是setup代码获得的,在进入main函数前按照Boot_Info *类型作为参数压入。

如下 

    xor eax, eax 
    mov ax, [(SETUPSEG<<4)+mem_size_kbytes]
    push    eax     ; memSizeKB
    push    dword 8     ; bootInfoSize

    ; Pass pointer to Boot_Info struct as argument to kernel
    ; entry point.
    push    esp     ;注意这里,传入的是一个指针!!作为Main函数的参数

    ; Push return address to make this look like a call , yes, it like a call. 
    ; XXX - untested
    push    dword (SETUPSEG<<4)+.returnAddr

    ; Far jump into kernel
    jmp KERNEL_CS:ENTRY_POINT ; 直接跳到Main函数入口处!!!!!!!

注意压入的参数是一个指针类型

Init_Mem函数位于./src/geekos/mem.c中,有点长了。

/*
 * Initialize memory management data structures.
 * Enables the use of Alloc_Page() and Free_Page() functions.
 */
void Init_Mem(struct Boot_Info* bootInfo)
{
    ulong_t numPages = bootInfo->memSizeKB >> 2;
    ulong_t endOfMem = numPages * PAGE_SIZE;
    unsigned numPageListBytes = sizeof(struct Page) * numPages;
    ulong_t pageListAddr;
    ulong_t kernEnd;

    KASSERT(bootInfo->memSizeKB > 0);

    /*
     * Before we do anything, switch from setup.asm's temporary GDT
     * to the kernel's permanent GDT.
     */
    Init_GDT();

    /*
     * We'll put the list of Page objects right after the end
     * of the kernel, and mark it as "kernel".  This will bootstrap
     * us sufficiently that we can start allocating pages and
     * keeping track of them.
     */
    pageListAddr = Round_Up_To_Page((ulong_t) &end);
    g_pageList = (struct Page*) pageListAddr;
    kernEnd = Round_Up_To_Page(pageListAddr + numPageListBytes);
    s_numPages = numPages;

    /*
     * The initial kernel thread and its stack are placed
     * just beyond the ISA hole.
     */
    KASSERT(ISA_HOLE_END == KERN_THREAD_OBJ);
    KASSERT(KERN_STACK == KERN_THREAD_OBJ + PAGE_SIZE);

    /*
     * Memory looks like this:
     * 0 - start: available (might want to preserve BIOS data area)
     * start - end: kernel
     * end - ISA_HOLE_START: available
     * ISA_HOLE_START - ISA_HOLE_END: used by hardware (and ROM BIOS?)
     * ISA_HOLE_END - HIGHMEM_START: used by initial kernel thread
     * HIGHMEM_START - end of memory: available
     *    (the kernel heap is located at HIGHMEM_START; any unused memory
     *    beyond that is added to the freelist)
     */

    Add_Page_Range(0, PAGE_SIZE, PAGE_UNUSED);
    Add_Page_Range(PAGE_SIZE, KERNEL_START_ADDR, PAGE_AVAIL);
    Add_Page_Range(KERNEL_START_ADDR, kernEnd, PAGE_KERN);
    Add_Page_Range(kernEnd, ISA_HOLE_START, PAGE_AVAIL);
    Add_Page_Range(ISA_HOLE_START, ISA_HOLE_END, PAGE_HW);
    Add_Page_Range(ISA_HOLE_END, HIGHMEM_START, PAGE_ALLOCATED);
    Add_Page_Range(HIGHMEM_START, HIGHMEM_START + KERNEL_HEAP_SIZE, PAGE_HEAP);
    Add_Page_Range(HIGHMEM_START + KERNEL_HEAP_SIZE, endOfMem, PAGE_AVAIL);

    /* Initialize the kernel heap */
    Init_Heap(HIGHMEM_START, KERNEL_HEAP_SIZE);

    Print("%uKB memory detected, %u pages in freelist, %d bytes in kernel heap\n",
	bootInfo->memSizeKB, g_freePageCount, KERNEL_HEAP_SIZE);
}

先看前两句
ulong_t numPages = bootInfo->memSizeKB >> 2;
ulong_t endOfMem = numPages * PAGE_SIZE;


实际调试中,bootInfo->memSizeKB = 32768

numPages=8192 PAGE_SIZE则是一个物理页的大小4K,
endOfMem为8192*4K,为32768K


memSizeKB是系统可用的物理内存,以K为单位,系统为每一个4K的物理页建立一个描述项,numPages得到描述项的个数。

endOfMem则得到可用内存的最终地址。
比如说如果boot_SIZE为32769,那么最终得到endOfMem为32768,剩余的1K不用,因为这个物理页不完整,无法用一个描述项描述。

下一句
unsigned numPageListBytes = sizeof(struct Page) * numPages;
得到这些描述项共占内存大小。


struct Page是物理页描述项的类型

定义在./include/geekos/mem.h中
/*
 * Each page of physical memory has one of these structures
 * associated with it, to do allocation and bookkeeping.
 */
struct Page {
    unsigned flags;                      /* Flags indicating state of page */
    DEFINE_LINK(Page_List, Page);        /* Link fields for Page_List */
};


其中DEFINE_LINK()是一个宏,定义在./include/geekos/list.h中

/*
 * Define members of a struct to be used as link fields for
 * membership in given list type.
 */
#define DEFINE_LINK(listTypeName, nodeTypeName) \
    struct nodeTypeName * prev##listTypeName, * next##listTypeNa
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值