歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 理解Linux的啟動過程(二)

理解Linux的啟動過程(二)

日期:2017/2/25 10:38:04   编辑:Linux教程

  3,加載內核

  在grub的菜單選定啟動Linux後,系統從Linux所在的磁盤載入內核。內核一般位於/boot目錄中,比如,我的系統中內核為 /boot/vmlinuz-2.6.12-10-686。當然,可以有不同版本的內核位於/boot目錄中,可以通過grub菜單選擇啟動的內核版本。

  $ uname -r : 顯示當前運行的內核版本

  vmlinuz是可引導的、壓縮的內核。“vm”代表“Virtual Memory”。vmlinux是未壓縮的內核,vmlinuz是vmlinux的壓縮文件.

  加載內核時還應該注意”虛擬硬盤“,即RAM DISK。以後有機會再歸納。


圖1 有建立RAM Disk可能的啟動流程


圖2 更明了的啟動流程

  總之,boot loader現將Linux內核加載到內存中(可能基於initrd建立RAM DISK),然後將BIOS中關於設備的數據傳遞給內核,內核建設設備,加載相應的驅動程序.

  4,init進程

  內核被加載之後,它執行的第一個程序就是/sbin/init.init 它利用 /etc/inittab配置文件獲取開機等級 ( Run level ) 之外, 並基於run level 選擇開機時啟動的服務.

  通過 $ less /etc/inittab 查看開機init讀取的開機配置文件內容.注意下面這行:

  # The default runlevel.

  id:2:initdefault:

  Ubuntu默認的run level是2.正如前面所說,把它設置成2,3,4,5都是多用戶圖形模式登錄.千萬別設成0或6!

  關於init進程,這裡多說幾句(針對一般UNIX系統)

  pid=0 : swapper進程,用於進程調度.它位於內核內部,是系統進程.

  pid=1 : init進程, 有對應的程序/sbin/init,盡管運行它需要管理員權限,但實際上它是個用戶進程,不位於內核中.系統啟動時,內核被加載後調用init進程.

  pid=2 : pagedaemon, 用於支持虛擬內存的頁.

  init進程還負責處理孤兒進程(父進程在子進程之前終止,則子進程成為孤兒進程, 此時,init繼承為他們的父進程).

  5,init 執行 /etc/init.d/rcS 程序 (重點)

  在Debian/Ubuntu系統中,初始化腳本是/etc/init.d/rcS,在Rad Hat中是/etc/rc.d/rc.sysinit。這裡面包含了裝入文件系統,設置時間,打開交換分區,得到主機名等等內容。

  在前面提到的inittab文件中,緊接runlevel之後有如下內容:

  # Boot-time system configuration/initialization script.

  # This is run first except when booting in emergency (-b) mode.

  si::sysinit:/etc/init.d/rcS

  inittab的主要功能是描述引導及正常操作時,應該在何種運行等級下啟動什麼程序,每個運行等級的具體項目完全可以通常/etc/inittab來定義,但Debian有一個更健壯的方案sysvinit,它被認為是init最強大的應用程序之一。Debian組織inittab的方式是把運行等級的大部分定義從inittab中移出來,移到一個腳本層次中去。惟一直接從inittab啟動的程序只有getty,它用於虛擬設備上啟動登錄提示符,保留它因為它們要求特殊處理,在inittab之外處理要困難得多。

  inittab來啟動所有軟件當然是可能的,但將所有配置寫在同一個文件既不方便查看也不方便維護,所以文件裡會加上這許多行:

  l0:0:wait:/etc/init.d/rc 0

  l1:1:wait:/etc/init.d/rc 1

  l2:2:wait:/etc/init.d/rc 2

  l3:3:wait:/etc/init.d/rc 3

  l4:4:wait:/etc/init.d/rc 4

  l5:5:wait:/etc/init.d/rc 5

  l6:6:wait:/etc/init.d/rc 6

  這些行實際決定了系統在各個運行等級下的行為。它們如何做到的也許並不明顯,但至少我們知道主要意思:首先每行都有個符號ID lx,lx表示runlevel x;其次,每行只在一個運行等級下激活,該運行等級對應著符號ID中的數字x。命令執行時,init停下來,直到進程結束。最後,每個命令行調用一個腳本 /etc/init.d/rc x,這裡x代表當前運行等級的數字。顯然各運行等級的具體任務在/etc/init.d/rcS腳本中安排。

  init把從inittab中獲取的run-level值作為參數傳遞給rc

  rc與rcS腳本的區別 (rc = run command)

  rc : This file is responsible for starting/stopping services when the runlevel changes.

  rcS : Call all S??* scripts in /etc/rcS.d in numerical/alphabetical order.

  6,加載內核模塊(module)

  2.6的內核支持動態模塊的加載,關於內核模塊,我另外寫一篇。

  7,init 執行 對應run-level 級的腳本文件( Scripts )

  到目前為止,內核及其模塊被加載了,也完成了系統的初始化。現在要做的工作就是開啟系統服務。由於不同的run-level需要開啟的服務不同,所以系統為不同的run-level設定了不同的腳本。

  $ ls -d /etc/rc*.d

  可以看到有rc0~rc6及rcS,共8個目錄。他們所包含的文件都是連接,指向/etc/init.d/目錄中的文件。比較各目錄中的文件你會發現, rc2~rc5中的內容是相同的。正好驗證了Debian/Ubuntu中run-level 2~5是等效的。

  以S開頭的表示在對應級別Start的服務,以K開頭表示Kill的服務。緊跟S或K之後的兩位數字決定了啟動順序,數字小的先運行。

  關於rcS/rcS.d,我還不是很清楚,哪位大俠指點?

  8,執行 /bin/login 程序,等待用戶登入

  這個就不用多說了。看過APUE的都知道login要讀取/etc/passwd文件。關於passwd文件,請參考APUE,p161 (第二版新版哦!)

  OK,完畢,謝謝收看。有不足之處,懇請指正!

  在系統加電引導時,init從run-level = 0開始,一級一級往上運行到inittab中定義的默認run-level。在run-level過渡時,init將run-level值作為參數傳遞給rc,進而執行啟動腳本。

Copyright © Linux教程網 All Rights Reserved