第三週:構造一個簡單的LINUX系統MENUOS

呂鬆鴻 + 原創做品轉載請註明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000
linux

1、Linux內核源碼簡介

1.操做系統的兩把寶劍shell

  •   中斷上下文的切換——保存現場&恢復現場
  •   進程上下文的切換

2.Linux內核源代碼簡介tcp

(1)打開內核源代碼頁面函數

  •   arch/目錄:支持不一樣CPU的源代碼;其中的X86是重點
  •   init/目錄:內核啓動相關的代碼基本都在該目錄中
  •   start_kernel函數就至關於普通C程序的main函數
  • kernel/目錄:Linux內核核心代碼在kernel目錄中

(2)READMEoop

提供內核的各類編譯方法、生成文件的查看方法。例如:ui

  •   INSTALLING 如何安裝內核源代碼
  •   make mrproper 清理安裝時生成的中間代碼

2、構造一個簡單的Linux系統

1. 運行MenuOS系統spa

在實驗樓的虛擬機環境裏,打擊打開shell,使用下面的命令操作系統

cd LinuxKernel/

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

# -initrd:指明一個根文件系統

  • 啓動實驗的Linux系統MenuOS,實際上就是一個在Linux內核的基礎上,再運行一個簡單菜單命令行程序。
  • 在MenuOS>的提示符下輸入help,看到其所有支持的命令:命令行

    help、version、quit

2. 使用gdb跟蹤調試內核

  • 使用帶參數命令啓動MenuOS,使得系統在剛啓動時,暫停等待調試器跟蹤執行。線程

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
    # -S 在CPU初始化以前,凍結CPU
    # -s 1234端口上建立一個tcp接口。若不想使用1234端口,則可使用-gdb tcp:xxxx來取代-s選項  
  • 另開一個shell窗口,啓動gdb。

    (gdb)file linux-3.18.6/vmlinux
    # 在gdb界面中targe remote以前加載符號表
    (gdb)target remote:1234 
    # 創建gdb和gdbserver之間的鏈接,按c 讓qemu上的Linux繼續運行
    (gdb)break start_kernel 
    # 在start_kernel函數入口處設置斷點
    (gdb)c 
    # 使得系統運行到start_kernel處停住
    (gdb)list
    # 顯示當前行所在位置上下的代碼

 

3、簡單分析start_kernel

(1)全局變量 init_task

全局變量init_task,即手工建立的PCB,0號進程初始化,0號進程就是最終的idle。

500asmlinkage __visible void __init start_kernel(void)
501{
502 char *command_line;
503 char *after_dashes;
504
505 /*
506  * Need to run as early as possible, to initialize the
507  * lockdep hash:
508  */
509 lockdep_init();
510 set_task_stack_end_magic(&init_task);//init_task即手工建立的PCB,0號進程及最終的idle進程
511 smp_setup_processor_id();
512 debug_objects_early_init();

(2)初始化一些中斷向量 trap_init()

中斷向量表的初始化函數,設置了不少中斷門(Interrupt Gate)

set_intr_gate:設置中斷門

(3)內存管理模塊初始化 mm_init()

(4)調度模塊初始化 sched_init()

函數內作了很關鍵的一步初始化——對0號進程,即idle進程進行初始化。

(5)其它模塊初始化 rest_init()

kernel_thread(kernel_init,NULL,CLONE_FS)中的kernel_init包含一個run_init_process,建立了一號進程,即第一個用戶態進程。以後建立了kthreadd,一個內核線程來管理系統的資源。

 

  •   建立了一號進程後,kernel_thread函數經過405行的kthreadd管理線程;
  •   由cpustartupentry(CPUHPONLINE);——>cpuidleloop();——>static void cpuidle_loop(void):
  •   cpuidleloop中有一個while循環,當start_kernel啓動以後,她就一直存在。當系統沒有進場須要執行的時候就調度到idle進程

4、總結

1.kernelthread是0號進程,它建立了1號進程kernelinit,以及它的一些服務的內核線程,這樣整個系統及啓動起來了;

2.而後init進程會再啓動一些進程。

相關文章
相關標籤/搜索