• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-80  評論-24  文章-0  trackbacks-0
            終于跳轉到main.c文件中的cbegin()函數執行了,這是從boot到loader再到內核,第一次執行c代碼的地方。我們先看main.c都做了什么。

             1 #include <type.h>
             2 #include <asm/system.h>
             3 #include <winixj/clock.h>
             4 #include <winixj/mm.h>
             5 #include <winixj/hdd.h>
             6 #include <winixj/sys_call.h>
             7 #include <winixj/process.h>
             8 #include <getpid.h>
             9 
            10 //指向在loader.s中保存的系統參數表
            11 //包括顯示卡參數、硬盤參數等等
            12 void *sys_param = (void *)0xf0000;
            13 volatile int cursor_pos = 0;
            14 
            15 
            16 //這個函數是真正的第一個C函數,從_start函數中跳入
            17 //最好將cbegin函數用volatile關鍵字修飾,這樣做的好處
            18 //是:用volatile修飾函數的話則是告訴gcc編譯器該函數
            19 //不返回(可能是函數內含有exit()或者死循環之類的),這樣
            20 //gcc在函數優化的時候就不會將返回值壓入堆棧,這樣,起到
            21 //優化的作用,在cbegin中start_proc0()啟動了第一個init進程
            22 //下面的for循環永遠不可能執行到,就算執行到那cbegin()也不會
            23 //返回
            24 void cbegin()
            25 {
            26     //初始化系統調用,包括將0x30號中斷與自陷框架sys_call函數掛鉤
            27     //以及安裝對用系統調用號的中斷入口函數
            28     init_sys_call();
            29     //初始化proc_list進程鏈表以及對init和sys進程進行初始化
            30     init_proc_list();
            31     //初始化心跳值為0,以及打開時鐘中斷、初始化開機時間等
            32     init_clock();
            33     init_mm();
            34 
            35     //這里調試了很久!!!!!!!!!!
            36     //注意這里一定要開中斷,因為當前中斷是關閉的
            37     //init_hd()中有涉及到硬盤中斷的操作
            38     //如果中斷關閉那么將響應不到硬盤中斷
            39     sti();
            40     init_hd();
            41     cli();
            42 
            43     //啟動第一個進程也即0號init進程
            44     start_proc0();
            45 
            46     //下面的代碼應該永遠不會被執行,因為start_proc0()函數不會返回,
            47     //start_proc0()函數執行完iretd命令后便啟動了第一個init進程,
            48     //自此系統便開始了多進程的運行
            49     for(;;){}
            50 }
            51 
            52 //proc0
            53 //第一個進程
            54 void init()
            55 {
            56     int i;
            57     uint8 *= (uint8 *)(0xb8000);
            58     *= (uint8)getpid() + '0';
            59 
            60     for(;;)
            61     {
            62         for ( i = 0; i < 1000000++i);
            63 
            64         if (*< '9')
            65         {
            66             *= ++(*p);
            67         }
            68     };
            69 }
            70 
            71 //proc1
            72 //第二個進程
            73 void sys()
            74 {
            75     int i;
            76     //這里由sys進程調用partition()系統調用來完成硬盤的初始化
            77     //之所以在不在內核中完成硬盤的初始化是因為這里需要讀取硬盤
            78     //MBR的內容,而讀取硬盤需要將當前進程睡眠,而內核是不允許
            79     //睡眠的,因此選擇在sys進程中初始化硬盤
            80     //這里的工作包括獲取硬盤柱面、柱頭、磁道、每磁道扇區數等的
            81     //信息
            82     uint8 *= (uint8 *)(0xb8002);
            83     *= (uint8)getpid() + '0';
            84 
            85     for(;;)
            86     {
            87         for ( i = 0; i < 1000000++i);
            88 
            89         if (*< '9')
            90         {
            91             *= ++(*p);
            92         }
            93     };
            94 }
            95 

            代碼量并不多,但是完成的事情其實并不少,主要的函數以及功能如下:
            1、init_sys_call 初始化系統調用
            2、init_proc_list 初始化進程控制塊數組
            3、init_clock 初始化時鐘中斷
            4、init_mm 初始化告訴緩沖區
            5、init_hd 初始化硬盤及硬盤中斷
            6、start_proc0 啟動第一個進程init進程
            其中每一項功能的實現都不簡單,之后的章節再一一詳細論述。
            這里有必要將內存分配的情況展示一下:
            在boot執行過程中:
            1、首先BIOS將自動從軟盤第一扇區讀取boot代碼(共512B),然后將其加載到內存物理地址0x7c00處,開始執行第一條代碼,boot開始執行。
            2、我們的boot程序完成從軟盤的第二個扇區開始將loader和kernel Image加載到物理地址0x80000開始的地方,然后便急切的跳轉到0x80000地址處去執行loader。
            3、loader此時開始執行,它首先分析kernel Image,將其各個段(包括若干代碼段、數據段等)復制到內存合適的地址處(我們編譯內核的時候指定了內核起始虛擬地址為0x0,由于我們的分段機制使得虛擬地址等于線性地址,所以內核開始執行時的線性地址也是0x0,又由于此時分頁機制是地址對等映射,所以物理地址也同樣是0x0,所以我們是將內核搬運到內存起始物理地址0x0開始運行的);然后從BIOS ROM區獲取一些系統參數,將參數保存在物理地址0xf0000開始的地方;之后準備GDT,并填充適當的GDT描述符項,然后通過打開A20地址線和置cr0寄存器最后一位PE位為1來打開保護模式,然后跳轉到保護模式運行;而進入保護模式之后loader什么也不干,畢竟我們想盡快的到內核世界去旅行,所以這里只簡單的跳轉到kernel去執行。
            至此為止,boot運行完成時的內存分布如下:



            而當loader執行完畢后的內存分布如下:



            之后內存分布不會有太大的變化。
            posted on 2012-02-14 13:01 myjfm 閱讀(601) 評論(0)  編輯 收藏 引用 所屬分類: 操作系統
            无码国内精品久久综合88| 亚洲国产精品综合久久一线| 久久精品国产99久久久| 99久久免费国产特黄| 国产精品成人久久久久三级午夜电影 | 九九久久精品国产| 漂亮人妻被中出中文字幕久久| 日日躁夜夜躁狠狠久久AV| 久久免费小视频| 一本色道久久88—综合亚洲精品| AV无码久久久久不卡网站下载| 久久久精品日本一区二区三区| 浪潮AV色综合久久天堂| 久久综合成人网| 久久综合久久综合久久| 久久妇女高潮几次MBA| 久久精品亚洲福利| 91精品国产乱码久久久久久| 中文字幕亚洲综合久久菠萝蜜| 伊人久久精品线影院| 久久精品国产清高在天天线| 久久亚洲日韩看片无码| 日本高清无卡码一区二区久久| 久久国产精品99精品国产987| 久久久久久精品久久久久| 思思久久99热免费精品6| 精品国产热久久久福利| 色综合久久中文综合网| 国内精品久久久久| 国产亚洲美女精品久久久久狼| 人妻精品久久无码区| 亚洲中文字幕无码一久久区| 久久久这里只有精品加勒比| 久久亚洲欧洲国产综合| 国产精品欧美亚洲韩国日本久久| 久久99国产精品久久99| 亚洲精品高清国产一久久| 国产亚洲精久久久久久无码AV| 国产高清国内精品福利99久久| 国产综合免费精品久久久| 久久久久久久久久免免费精品|