• <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)  編輯 收藏 引用 所屬分類: 操作系統
            99精品国产99久久久久久97| 久久久久99这里有精品10| 丁香狠狠色婷婷久久综合| 久久精品国产亚洲综合色| 久久九色综合九色99伊人| 久久久无码精品亚洲日韩京东传媒 | 日日狠狠久久偷偷色综合96蜜桃| 2021国内精品久久久久久影院| 久久精品人人槡人妻人人玩AV | 午夜精品久久久久久久| 九九久久精品无码专区| 久久久久久久久久久久中文字幕 | 久久亚洲国产成人精品性色| 久久精品国产精品亚洲下载| 久久综合狠狠综合久久综合88| 亚洲成av人片不卡无码久久| 91久久精品电影| 大伊人青草狠狠久久| 久久久久99精品成人片试看| 无码任你躁久久久久久老妇App| 精品久久人人做人人爽综合 | 久久国产色av免费看| 日本久久中文字幕| 久久福利片| 久久国产免费直播| 久久国产精品偷99| 久久久久国产亚洲AV麻豆| 91秦先生久久久久久久| 久久精品国产福利国产秒| 国产成人久久精品一区二区三区| 亚洲欧美日韩中文久久| 久久天堂AV综合合色蜜桃网| 久久婷婷五月综合国产尤物app| 伊人久久精品无码二区麻豆| 中文无码久久精品| 久久国产亚洲精品无码| 91久久精品91久久性色| 天天综合久久久网| 理论片午午伦夜理片久久| 亚洲人成网站999久久久综合 | 久久99精品国产|