亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 5386 | 回復: 3
打印 上一主題 下一主題

MINIX3內(nèi)核初始化過程 [復制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2007-06-11 15:23 |只看該作者 |倒序瀏覽
MINIX3內(nèi)核被成功加載到內(nèi)存后,控制權(quán)會轉(zhuǎn)移到kernel/mpx.s文件,根據(jù)機器字長為16位或32位來分別加載mpx88.s或者mpx386.s文件并執(zhí)行。

此時,csds寄存器已經(jīng)指向MINIX3內(nèi)核的相應段,而ss寄存器仍指向boot的棧段,該棧中結(jié)構(gòu)如下:
(棧底)
aout結(jié)構(gòu)體的地址
boot參數(shù)的大小和地址
boot的CS和IP(16位),以便MINIX3結(jié)束后將控制權(quán)交還給boot
(棧頂)

對于32PC機,MINIX3內(nèi)核會跳轉(zhuǎn)到mpx386.s文件的MINIX標簽處開始執(zhí)行:
MINIX:
    jmp    over_flags        ! 跳過下面兩個用于boot的數(shù)據(jù)
    .data2    CLICK_SHIFT
flags:
    .data2    0x01FD
    nop
over_flags:

! 設置boot棧,以便MINIX3結(jié)束后交還控制權(quán)
    movzx    esp, sp        ! 將boot棧擴展為32位
    push    ebp        ! 將棧頂?shù)刂穫魉徒oebp
    mov    ebp, esp
    push    esi
    push    edi
    cmp    4(ebp), 0        ! 如果boot的cs和ip均為0則不可交還控制權(quán)
    jz    noret
    inc    (_mon_return)
noret:    mov    (_mon_sp), esp    ! 保存ESP的值

! 將boot的GDT拷貝到內(nèi)核地址空間,并加載
    sgdt    (_gdt+GDT_SELECTOR)        ! 將GDT的描述結(jié)構(gòu)拷貝到內(nèi)存
                    ! 低2字節(jié)為字節(jié)長,高4字節(jié)為基址
    mov    esi, (_gdt+GDT_SELECTOR+2)    ! boot中GDT的基址
    mov    ebx, _gdt            ! 內(nèi)核中GDT的基址
    mov    ecx, 8*8            ! 拷貝前8個描述符
copygdt:
eseg    movb    al, (esi)            ! eseg說明操作數(shù)的段寄存器為es
    movb    (ebx), al
    inc    esi
    inc    ebx
    loop    copygdt
    mov    eax, (_gdt+DS_SELECTOR+2)    ! 設置GDT基址
    and    eax, 0x00FFFFFF
    add    eax, _gdt
    mov    (_gdt+GDT_SELECTOR+2), eax
    lgdt    (_gdt+GDT_SELECTOR)        ! 加載GDT

! 設置內(nèi)核段寄存器和棧
    mov    ebx, 8(ebp)    ! boot參數(shù)地址
    mov    edx, 12(ebp)    ! boot參數(shù)長度
    mov    eax, 16(ebp)    ! a.out頭地址
    mov    (_aout), eax
    mov    ax, ds
    mov    es, ax
    mov    fs, ax
    mov    gs, ax
    mov    ss, ax
    mov    esp, k_stktop

! 調(diào)用start.c文件中的cstart函數(shù)來保存內(nèi)核信息
    push    edx
    push    ebx
    push    SS_SELECTOR
    push    DS_SELECTOR
    push    CS_SELECTOR
    call    _cstart
    add    esp, 5*4

! 重新加載GDT和IDT
    lgdt    (_gdt+GDT_SELECTOR)
    lidt    (_gdt+IDT_SELECTOR)

    jmpf    CS_SELECTOR:csinit    ! 開始使用剛初始化好的表
csinit:
! 初始化段選擇子
o16    mov    ax, DS_SELECTOR    ! o16說明操作數(shù)為16位
    mov    ds, ax
    mov    es, ax
    mov    fs, ax
    mov    gs, ax
    mov    ss, ax
o16    mov    ax, TSS_SELECTOR    ! 初始化任務狀態(tài)段(TSS)
    ltr    ax
    push    0        ! 將eflags清0
    popf

! 調(diào)用main.c文件中的main函數(shù)運行boot image
    jmp    _main

其中,start.c文件中的cstart函數(shù)實現(xiàn)如下:
PUBLIC void cstart(cs, ds, mds, parmoff, parmsize)
U16_t cs, ds;        [color=#FF9900>// 內(nèi)核代碼段與數(shù)據(jù)段

U16_t mds;            [color=#FF9900>// boot數(shù)據(jù)段

U16_t parmoff, parmsize;    [color=#FF9900>// boot參數(shù)地址與長度

{
    char params[128*sizeof(char *)];
    register char *value;
    extern int etext, end;

#if _WORD_SIZE != 2
    [color=#FF9900>// 如果是386+則設置保護模式

    machine.protected = 1;   
#endif

    [color=#FF9900>// 保存內(nèi)核代碼段和數(shù)據(jù)地址與長度

    kinfo.code_base = seg2phys(cs);
    kinfo.code_size = (phys_bytes) &etext;
    kinfo.data_base = seg2phys(ds);
    kinfo.data_size = (phys_bytes) &end;

    [color=#FF9900>// 初始化保護模式下的描述符

    prot_init();

    [color=#FF9900>// 將boot參數(shù)拷貝到本地

    kinfo.params_base = seg2phys(mds) + parmoff;    [color=#FF9900>// boot參數(shù)地址

    kinfo.params_size = MIN(parmsize,sizeof(params)-2);    [color=#FF9900>// boot參數(shù)長度

    phys_copy(kinfo.params_base, vir2phys(params), kinfo.params_size);
                        [color=#FF9900>// 源 目的 長度


    [color=#FF9900>// 保存其他信息

    kinfo.nr_procs = NR_PROCS;
    kinfo.nr_tasks = NR_TASKS;
    strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));    [color=#FF9900>// 目的 源 長度

    kinfo.release[sizeof(kinfo.release)-1] = '\0';
    strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
    kinfo.version[sizeof(kinfo.version)-1] = '\0';
    kinfo.proc_addr = (vir_bytes) proc;
    kinfo.kmem_base = vir2phys(0);
    kinfo.kmem_size = (phys_bytes) &end;   

    [color=#FF9900>// 獲取CPU類型

    machine.processor=atoi(get_value(params, "processor"));
#if _WORD_SIZE == 2
    machine.protected = machine.processor >= 286;        
#endif
    if (!machine.protected) mon_return = 0;

    [color=#FF9900>// 獲取總線類型

    value = get_value(params, "bus");
    if (value == NIL_PTR || strcmp(value, "at") == 0) {
        machine.pc_at = TRUE;
    } else if (strcmp(value, "mca") == 0) {
        machine.pc_at = machine.ps_mca = TRUE;
    }

    [color=#FF9900>// 獲取顯示器類型

    value = get_value(params, "video");
    if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
    if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
}

論壇徽章:
0
2 [報告]
發(fā)表于 2007-06-11 15:23 |只看該作者
main.c文件中的main函數(shù)實現(xiàn)如下:
PUBLIC void main()
{
    struct boot_image *ip;
    register struct proc *rp;
    register struct priv *sp;
    register int i, s;
    int hdrindex;
    phys_clicks text_base;
    vir_clicks text_clicks, data_clicks;
    reg_t ktsb;
    struct exec e_hdr;

    [color=#FF9900>// 初始化中斷控制器

    intr_init(1);

    [color=#FF9900>// 初始化進程表與特權(quán)控制表

    for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
        rp->p_rts_flags = SLOT_FREE;
        rp->p_nr = i; from ptr */
        (pproc_addr + NR_TASKS)[i] = rp;
    }
    for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
        sp->s_proc_nr = NONE;
        sp->s_id = i;
        ppriv_addr[i] = sp;
    }

    [color=#FF9900>// 任務棧

    ktsb = (reg_t) t_stack;

    [color=#FF9900>// 初始化boot image中的進程

    for (i=0; i < NR_BOOT_PROCS; ++i) {
        ip = &image[i];
        rp = proc_addr(ip->proc_nr);        [color=#FF9900>// 進程描述符

        rp->p_max_priority = ip->priority;    [color=#FF9900>// 最大調(diào)度優(yōu)先級

        rp->p_priority = ip->priority;        [color=#FF9900>// 當前調(diào)度優(yōu)先級

        rp->p_quantum_size = ip->quantum;    [color=#FF9900>// 時間片

        rp->p_ticks_left = ip->quantum;        [color=#FF9900>// 當前剩余時間片

        strncpy(rp->p_name, ip->proc_name, P_NAME_LEN);    [color=#FF9900>// 進程名

        (void) get_priv(rp, (ip->flags & SYS_PROC));    [color=#FF9900>// 獲取特權(quán)級

        priv(rp)->s_flags = ip->flags;        [color=#FF9900>// 設置進程特權(quán)級標識

        priv(rp)->s_trap_mask = ip->trap_mask;    [color=#FF9900>// 設置允許使用的系統(tǒng)調(diào)用

        priv(rp)->s_call_mask = ip->call_mask;    [color=#FF9900>// 設置允許使用的內(nèi)核調(diào)用        priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to;    // 可向其發(fā)送消息的進程

        if (iskerneln(proc_nr(rp))) {
            [color=#FF9900>// 如果是內(nèi)核進程則設置棧保護

            if (ip->stksize > 0) {
                [color=#FF9900>// KERNEL進程的棧為0

                rp->p_priv->s_stack_guard = (reg_t *) ktsb;
                *rp->p_priv->s_stack_guard = STACK_GUARD;
            }
            ktsb += ip->stksize;    [color=#FF9900>// 棧底

            rp->p_reg.sp = ktsb;    [color=#FF9900>// 棧頂

            text_base = kinfo.code_base >> CLICK_SHIFT;
            hdrindex = 0;    [color=#FF9900>// 所有內(nèi)核進程被編譯成同一文件

        } else {
            hdrindex = 1 + i-NR_TASKS;
        }

        [color=#FF9900>// 從boot拷貝a.out頭的exec結(jié)構(gòu)體

        phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr),
                        (phys_bytes) A_MINHDR);
        [color=#FF9900>// 使用clicks表示地址

        text_base = e_hdr.a_syms >> CLICK_SHIFT;
        text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
        if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0;
        data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
        [color=#FF9900>// 構(gòu)建進程內(nèi)存映像

        rp->p_memmap[T].mem_phys = text_base;
        rp->p_memmap[T].mem_len = text_clicks;
        rp->p_memmap[D].mem_phys = text_base + text_clicks;
        rp->p_memmap[D].mem_len = data_clicks;
        rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks;
        rp->p_memmap[S].mem_vir = data_clicks;

        [color=#FF9900>// 設置初始化寄存器值

        rp->p_reg.pc = (reg_t) ip->initial_pc;
        rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW;

        if (isusern(proc_nr(rp))) {
            [color=#FF9900>// 初始化服務器棧指針(向下移動一個字),使其能接收argc參數(shù)

            rp->p_reg.sp = (rp->p_memmap[S].mem_vir +
                rp->p_memmap[S].mem_len) << CLICK_SHIFT;
            rp->p_reg.sp -= sizeof(reg_t);
        }

        if (rp->p_nr != HARDWARE) {
            [color=#FF9900>// 將進程設置為等待運行(ready)狀態(tài)

            rp->p_rts_flags = 0;
            lock_enqueue(rp);
        } else {
            [color=#FF9900>// 阻止KERNEL(HARDWARE)進程運行

            rp->p_rts_flags = NO_MAP;
        }

        [color=#FF9900>// 為進程分配代碼段和數(shù)據(jù)段

        alloc_segments(rp);
    } [color=#FF9900>// for循環(huán)結(jié)束


#if ENABLE_BOOTDEV
    [color=#FF9900>// 加載boot設備

    hdrindex++;
    phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
    if (e_hdr.a_flags & A_IMG) {
        kinfo.bootdev_base = e_hdr.a_syms;
        kinfo.bootdev_size = e_hdr.a_data;
    }
#endif

    bill_ptr = proc_addr(IDLE);    [color=#FF9900>// 設置IDLE為第一個運行的進程

    announce();        [color=#FF9900>// 顯示歡迎信息


    [color=#FF9900>// 調(diào)用mpx386.s文件中的_restart函數(shù)開始進程調(diào)度等

    restart();
}


到此為止,MINIX3的內(nèi)核就完成了全部的初始化工作,并開始通過進程調(diào)度來運行所有的進程。

論壇徽章:
0
3 [報告]
發(fā)表于 2007-07-09 23:15 |只看該作者
多謝樓主分享,十分感謝,收藏了!

論壇徽章:
0
4 [報告]
發(fā)表于 2007-07-10 10:31 |只看該作者
加油!加油!
對于我等,為你加油才是硬道理!
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP