[计算机操作系统] —— head&main

250 阅读1分钟

setup开启了实模式,移动system到内存0地址,并跳转到0地址,此时位于system的head模块。

; 之前的setup为了jmpi临时设置了gdt,这里重新设置
call setup_idt		call setup_gdt

; 设置页表,页表设置成功后,跳转到main.c
jmp after_page_tables
after_page_table:
	; 0 0 0是main的三个参数,L6是main的返回地址
	push $0		push $0		push $0 	push $L6	push $_main
    jmp setup_paging
L6: jmp L6	; main返回,系统就会死机,所以main不应该返回
setup_paging:
	...	; 设置页表
    ret	; 返回到main

head准备了有关数据结构,并跳转到了main.c执行。main的工作就是做内存、中断、设备、时钟、CPU等内容的初始化。

void main(void) {
	mem_init();
    trap_init();
    blk_dev_init();
    chr_dev_init();
    tty_init();
    time_init();
    sched_init();
    buffer_init();
    hd_init();
    floppy_init();
    sti();
  	move_to_user_mode();
    if(!fork()) {init();}
}

此处举例说明mem_init对内存的初始化操作。

// linux/mm/memory.c
void mem_init(long start_mem, long end_mem) {
	// end_mem就是多大内存,从0x90002获取
    int i;
    for(i = 0; i < PAGING_PAGES; ++i) {
    	mem_map[i] = USED;
    }
    i = MAP_NR(start_mem);
    end_mem -= start_mem;
    end_mem >>= 12;				// 每次把4k空间(页)置零
    while(end_mem-- > 0) {
    	mem_map[i++] = 0;
    }
}

mem_init()自高地址向低地址标记可用,永远标记低地址是已用,因为低地址存放着操作系统。