系统初始化程序
main.c程序首先利用前面setup.s程序取得的系統參數設置系統的根文件設備號以及一些內存全局變量。這些內存變量指明了主內存的開始地址、系統所擁有的內存容量和作為高速緩沖區的末端地址。如果還定義了虛擬盤(RAMDISK),則主內存將適當減少。該程序確定如何分配使用系統物理內存,然后調用內核各部分的初始化函數分別對內存管理、中斷處理、塊設備和字符設備、進程管理以及硬盤和軟盤硬件進行初始化處理。在完成這些操作之后,系統各部分就已經處于可運行狀態。
??? 內核進行所有方面的硬件初始化工作,包括陷阱門、塊設備、字符設備和tty,包括手工設置第一個任務。待所有初始化工作完成后程序就設置中斷允許標志以開啟中斷,mai()也切換到了任務0中運行。
??? 在整個內核完成初始化后,內核將執行權切換到了用戶模式,此時main.c的主程序就工作在任務0中。然后系統第一次調用進程創建函數fork(),創建出一個用于運行init()的子進程。在該函數中程序將繼續進行應用環境的初始化并執行shell登陸程序。而原進程0則會在系統空閑時被調度執行,因此進程0通常也被稱為idle進程。此時進程0僅執行pause()系統調用,并又會調用調度函數。
??? init()函數的功能可氛圍4個部分:(1)安裝根文件系統(2)顯示系統消息(3)運行系統初始資源配置文件rc中的命令(4)執行用戶登陸shell程序。
??? 代碼首先調用setup(),用來收集硬盤設備分區表信息并安裝根文件系統。在安裝根文件系統之前系統會先判斷是否需要先建立虛擬盤。若編譯內核時設置了虛擬盤的大小,并在前面內核中已經開辟了一塊內存用作虛擬盤,則內核就會首先嘗試把根文件系統加載到內存的虛擬盤區中。
??? 然后init()打開一個中斷設備tty0,并復制其文件描述符以產生標準輸入stdin、標準輸出stdout和錯誤輸出stderr設備。內核隨后利用這些描述符在終端上顯示一些系統信息。接著init()又新建一個進程(進程2),并在其中為建立用戶交互使用環境而執行一些初始配置操作,即在用戶可以使用shell命令行環境之前,內核調用/bin/sh程序運行了配置文件etc/rc中設置的命令。rc文件的作用與DOS系統根目錄上的AUTOEXEC.BAT文件類似。這段代碼首先通過關閉文件描述符0,并立刻打開文件/etc/rc,從而把標準輸入stdin定向到etc/rc文件。這樣,所有的 標準輸入數據都將從該文件中讀取。然后內核以非交互式執行/bin/sh,從而實現執行/etc/rc文件中的命令。當該文件中的命令執行完畢后,/bin/sh就會立刻退出。因此進程2也就隨之結束。
????inti()函數的最后一部分在新建進程中為用戶建立一個新的會話,并運行用戶登陸shell程序/bin/sh。在系統執行進程2中的程序時,父進程(init進程)一直等待著它的結束。隨著進程2的退出,父進程就進入到一個無限循環中。在該循環中,父進程會再次生成一個新進程,然后在該進程中創建一個新的會話,并以登陸shell方式再次執行程序/bin/sh,以創建用戶交互shell環境。然后父進程繼續等待該子進程。登陸shell雖然與前面的非交互方式shell是同一個程序/bin/sh,但是所使用的命令行參數不同。從這時開始,用戶就可以正常使用linux命令行環境了,而父進程隨之又進入等待狀態。此后若用戶在命令行上執行了exit或logout命令,那么在顯示一條當前登陸shell退出的信息后,系統就會在這個無限循環中再次重復以上創建登陸shell進程的過程。
??? 由于創建新進程的過程是通過完全復制父進程代碼段和數據段的方式實現,因此在首次使用fork()創建新進程init時,為了確保新進程用戶態棧中沒有進程0的多余信息,要求進程0在創建第一個新進程(進程1)之前不要使用其用戶態棧,即要求任務0不要調用函數。因此在main.c主程序移動到任務0執行后,任務0中的代碼fork()不能以函數形式進行調用。程序中的實現方法時采用gcc函數內嵌(內聯)形式來執行這個系統調用。
??? 內核進行所有方面的硬件初始化工作,包括陷阱門、塊設備、字符設備和tty,包括手工設置第一個任務。待所有初始化工作完成后程序就設置中斷允許標志以開啟中斷,mai()也切換到了任務0中運行。
??? 在整個內核完成初始化后,內核將執行權切換到了用戶模式,此時main.c的主程序就工作在任務0中。然后系統第一次調用進程創建函數fork(),創建出一個用于運行init()的子進程。在該函數中程序將繼續進行應用環境的初始化并執行shell登陸程序。而原進程0則會在系統空閑時被調度執行,因此進程0通常也被稱為idle進程。此時進程0僅執行pause()系統調用,并又會調用調度函數。
??? init()函數的功能可氛圍4個部分:(1)安裝根文件系統(2)顯示系統消息(3)運行系統初始資源配置文件rc中的命令(4)執行用戶登陸shell程序。
??? 代碼首先調用setup(),用來收集硬盤設備分區表信息并安裝根文件系統。在安裝根文件系統之前系統會先判斷是否需要先建立虛擬盤。若編譯內核時設置了虛擬盤的大小,并在前面內核中已經開辟了一塊內存用作虛擬盤,則內核就會首先嘗試把根文件系統加載到內存的虛擬盤區中。
??? 然后init()打開一個中斷設備tty0,并復制其文件描述符以產生標準輸入stdin、標準輸出stdout和錯誤輸出stderr設備。內核隨后利用這些描述符在終端上顯示一些系統信息。接著init()又新建一個進程(進程2),并在其中為建立用戶交互使用環境而執行一些初始配置操作,即在用戶可以使用shell命令行環境之前,內核調用/bin/sh程序運行了配置文件etc/rc中設置的命令。rc文件的作用與DOS系統根目錄上的AUTOEXEC.BAT文件類似。這段代碼首先通過關閉文件描述符0,并立刻打開文件/etc/rc,從而把標準輸入stdin定向到etc/rc文件。這樣,所有的 標準輸入數據都將從該文件中讀取。然后內核以非交互式執行/bin/sh,從而實現執行/etc/rc文件中的命令。當該文件中的命令執行完畢后,/bin/sh就會立刻退出。因此進程2也就隨之結束。
????inti()函數的最后一部分在新建進程中為用戶建立一個新的會話,并運行用戶登陸shell程序/bin/sh。在系統執行進程2中的程序時,父進程(init進程)一直等待著它的結束。隨著進程2的退出,父進程就進入到一個無限循環中。在該循環中,父進程會再次生成一個新進程,然后在該進程中創建一個新的會話,并以登陸shell方式再次執行程序/bin/sh,以創建用戶交互shell環境。然后父進程繼續等待該子進程。登陸shell雖然與前面的非交互方式shell是同一個程序/bin/sh,但是所使用的命令行參數不同。從這時開始,用戶就可以正常使用linux命令行環境了,而父進程隨之又進入等待狀態。此后若用戶在命令行上執行了exit或logout命令,那么在顯示一條當前登陸shell退出的信息后,系統就會在這個無限循環中再次重復以上創建登陸shell進程的過程。
??? 由于創建新進程的過程是通過完全復制父進程代碼段和數據段的方式實現,因此在首次使用fork()創建新進程init時,為了確保新進程用戶態棧中沒有進程0的多余信息,要求進程0在創建第一個新進程(進程1)之前不要使用其用戶態棧,即要求任務0不要調用函數。因此在main.c主程序移動到任務0執行后,任務0中的代碼fork()不能以函數形式進行調用。程序中的實現方法時采用gcc函數內嵌(內聯)形式來執行這個系統調用。
轉載于:https://blog.51cto.com/bluefish/38850
總結
- 上一篇: 转:Oracle 应用服务器 MapVi
- 下一篇: 一句话回复:关于'SqlMembersh