歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 探索Linux系統的啟動過程

探索Linux系統的啟動過程

日期:2017/2/28 14:21:34   编辑:Linux教程

閱讀目錄

  • 引言
  • Linux啟動過程概述
  • Grub加載Linux內核和initramfs
  • 探索initramfs文件的方法
  • 基於systemd的init系統
  • 進入圖形界面

這篇文章有點長,我花了大約兩個星期的時間才完成,雖然不是寫得巨細無遺,但是我認為還是很有價值的,求推薦。不管你是不是 Linux 愛好者,也不管你是否能耐心讀完,請果斷 mark 之,你值得擁有。

引言

  這一篇可能是我這系列隨筆除總結之外的最後一篇,也可能不是。為什麼這麼說呢?因為我覺得在 Linux 應用環境方面再寫下去也可能不會有什麼新意了,至少以我的水平寫不出什麼新意了。我的這一個系列,基本上不涉及到編程,而是真真正正地將 Linux 桌面系統當成日常使用的工具,即使在我的這個系列中有探討 C 語言或者 Bash 語言的部分,我也是展示的相關的開發工具,比如 binutils 工具包和 autotools 工具鏈。我曾經說過,折騰 Linux 就是折騰 Linux 系統下的軟件,Linux 世界軟件之多,可寫的應該還有不少,但是我覺得已經沒有辦法寫得很好了。比如有一些工作我還沒有找到適當的工具,像 JavaScript 和 CSS 開發,對於博客園中的廣大前端攻城獅來說,肯定是各有神通,但是我確實不知道用什麼工具可以做到即順手又高效率,我只會簡單地用用 Firefox 提供的開發者工具。還有 3D 開發、游戲編程、移動開發等等,雖然可以寫的領域比較廣闊,但是畢竟我不是做這些的,沒什麼經驗,不能說光寫某某軟件試用體驗吧。再說,程序員終歸還是程序員,以後寫博客應該還是介紹編程經驗比較好。

  之所以想到寫這些東西,那是因為我確實想讓大家也和我一樣,把 Linux 桌面系統打造成真真正正日常使用的工具,而不是安裝之後試用幾把再刪掉。我是真的在日常生活和工作中都使用 Linux,比如在 Linux 下編程、寫博客、寫論文和做幻燈。當然,對於 LibreOffice 這樣的軟件使用起來都不會有什麼困難,所以在我的博客中就基本沒有提到,就像 Windows 下的程序員不會去寫 MS Office 的使用指南一樣。如果有人不能堅持使用 Linux,那一定是 Linux 中的某些困難打敗了他。剛使用 Linux 時確實會碰到很多困難,比如界面不夠美觀啊、字體不夠順眼啊、輸入法太難用啊,還有就是想做某個工作找不到工具、想改一個屬性找不到入口、系統崩潰了無法恢復等等,甚至是剛安裝一個軟件包或者下載一個文件,卻不知道放到文件系統的什麼地方了。所以,我的這一個系列就是在向大家展示我的方法論,用什麼軟件不重要,怎麼用好也不重要,而是碰到問題了,用什麼思路去找答案,到哪裡去找答案。經過這二十幾篇的展示,我的方法論也基本上講完了。所以我決定,寫完這一篇探索 Linux 系統的啟動過程之後,我將開始另外一個系列的工作。

  關於 Linux 系統的啟動過程也是幾經變革。首先是操作系統從磁盤載入的過程發生了變化,很老舊的操作系統需要自己寫啟動扇區,現在的操作系統早就將這個過程交給了專門的啟動工具。最常用的操作系統加載程序是 Grub,這個名字大家肯定早就如雷灌耳了,而且 Grub 也已經從第1版發展到了第2版,我們稱之為 Grub2。 Grub2 和 Grub1 有很大的差別,網絡上有很多講 Linux 的文章動不動就拿 Grub1 說事兒,比如讓大家修改 menu.lst 文件這樣的,都是很過時的內容了。關於 Grub2 的詳細資料可以閱讀文檔info grub或者info grub2。Grub 的優點是支持多操作系統的啟動,Windows、Linux、BSD都不在話下,但是它們的啟動協議是不一樣的,啟動 Windows 靠的是 chainloader,啟動 Linux 直接使用 linux 命令,而 BSD 系統好像是使用的 multiboot,特別是 Grub 的 multiboot 規范對那些很想自己寫操作系統的程序員很有用,因為再也不用從啟動扇區的代碼開始寫了,可以直接進入保護模式用 C 語言寫操作系統。Linux 系統在啟動的時候還有 initrd 或 initramfs 機制,這個也需要 Linux 用戶特別注意。initrd 或 initramfs 也經歷過一次技術革新,最開始采用的是 RamDisk 技術,目前采用的 tmpfs 技術。最後,內核加載入內存後,會將系統初始化的控制權交給 init 程序,而 init 程序也不是一成不變的,最開始使用的是 SysVinit,後來又改成 Upstart,現在最流行的又變成了 systemd。現在仍然有很多書和網文講的還是 SysVinit 時代的做法,當然這些文章只能以 RedHat EL 5 以及之前的發行版作為示例,而對於最新的發行版,這些文章中講的方法又會給新入門的用戶造成困難。

  探索 Linux 系統的啟動過程是每一個 Linux 用戶進步到一定程度後必然要去做的一件事。有的人可能只是好奇,也有的人可能確實需要從啟動過程中去解決某一個特定的問題。這種探索我進行過多次,也早就想寫一寫,但是總是寫不好。這一次是借著 systemd 普及的東風,讓這個探索過程成為我這一系列的壓軸之作。為什麼說是借著 systemd 普及的東風呢?因為聽說本月即將發布的 Ubuntu 15.04 版本將會從 upstart 更換為 systemd,目前正在緊張地測試中。當然,一下子遷移過來對開發人員來講還是有點難度的,但是只要確定目標,即使 Ubuntu 15.04 不使用 systemd,到 15.10 也肯定是它了。因此,對於我這個喜歡折騰多個 Linux 發行版的人來說,就不用多線作戰了,只需要學好 systemd 即可。

Linux啟動過程概述

  這裡先簡單列一下 Linux 操作系統啟動的全過程:

  1. 按下電腦的電源鍵後,電腦通電,BIOS啟動;
  2. BIOS讀取硬盤的MBR,運行啟動扇區中的代碼,舊系統往往需要自己寫啟動扇區,而新系統基本上由專用的啟動軟件接管了,在 Linux 世界中,目前都是用的 Grub2。由於啟動扇區空間太小,放不下太復雜的代碼邏輯,所以 Grub2 也使用了多階段啟動的策略;
  3. Grub2 負責將操作系統內核加載到內存,如果有必要,也會把 initramfs 文件加載到內存,然後將控制權交給內核;
  4. 內核進行初始化,內核的初始化過程結束後,就會把控制權交給/init程序,從此進入用戶空間;
  5. 因為內核先是將 initramfs 文件掛在為根文件系統,所以剛開始運行的/init程序其實是 initramfs 文件中的,所以該文件需要的重要的初始化腳本、內核模塊、配置文件等,都位於 initramfs 文件中,這也是為什麼很多時候我們修改了某些配置文件後,需要先更新 initramfs 文件再重啟操作系統才會生效;
  6. initramfs 文件中的/init程序負責掛載硬盤上的文件系統,然後再把根文件系統切換到硬盤上的根分區,再運行/sbin/init程序,這時所有程序、配置文件、腳本都是使用的硬盤上的了,當然,網絡文件系統也是同理。可以看出 init 程序的運行也是一個分階段的過程;
  7. /sbin/init程序負責系統的初始化、各種服務的運行、用戶的登陸等等;
  8. 如果需要運行圖形界面,則/sbin/init程序會運行 Display Manager,在 Fedora 中是 gdm,在 Ubuntu 中是 lightdm。然後 Display Manager 負責啟動整個圖形界面。

Grub加載Linux內核和initramfs

  研究 Linux 啟動過程的第一站就是要研究 Grub。大部分時候我們不用考慮 Grub 的安裝,因為安裝 Linux 桌面系統的時候已經幫我們自動安裝好了,我們要做的,最多就是改改 Grub 的配置文件。只有在一種情況下需要手動安裝 Grub,那就是在系統崩潰後急救的時候,當然,需要先運行一個光盤版或 U 盤版的 Linux 系統,然後運行grub-install命令,這個命令需要指定將 Grub 安裝到那個硬盤的 MBR,具體操作看文檔即可。

  Grub2 和 Grub 相比,有了很多改進,改進到 Grub2 都相當於一個小型的操作系統了,比如 Grub2 能識別各種格式的硬盤分區及文件系統,能識別各種格式的圖像,甚至還能動態加載模塊。其中最重要的改變是配置文件由 Grub1 時代的/boot/menu.lst文件變成 Grub2 時代的/boot/grub/grub.cfg文件了(注意,有的系統中是/boot/grub2/grub.cfg,比如 Fedora),配置文件的語法也變復雜了很多。雖然 Grub2 配置文件的語法比較復雜,但是我們一般不需要直接修改該文件,而是修改/etc/default/grub文件後,再使用update-grub命令自動生成配置文件。當然,要完成一些簡單任務時對/boot/grub/grub.cfg文件進行直接修改也是可以的,只是一旦系統更新,則對該文件的修改有可能被覆蓋。

  Grub 最重要的任務就是加載 Linux 內核以及 initramfs 文件了,這幾個命令是非常簡單易懂的,在/boot/grub/grub.cfg文件中也非常容易找到,如下圖:

  上圖主要是展示 Grub 載入 Linux 內核並且給 Linux 內核傳遞參數的過程,同時展示載入 initramfs 文件的過程。

探索initramfs文件的方法

  Grub 將 Linux 內核和 initramfs 文件載入內存後,就把控制權交給內核,內核會將內存中的 initramfs 文件掛載為根文件系統,當內核初始化完成後需要進入用戶空間時,會運行/init,其實這個/init是在 initramfs 文件中的,所以如果想知道系統啟動後都干了些什麼,研究一下 initramfs 文件中的內容是有必要的。

  在/boot目錄下,一般都有一個/boot/initrd.img文件或一個/boot/initramfs.img文件,但是要看裡面的內容還得有點技巧。先得學習一下歷史。第一個問題就是為什麼要有 initrd 或者 initramfs,答案是這樣的,為了減小 Linux 內核的大小,有一些驅動並沒有編譯進內核,而是以模塊的形式存在於文件系統中,但是有些文件系統呢又需要內核加載了相應的驅動模塊才能讀取,這樣就形成了一個是先有雞還是先有蛋這樣的一個矛盾的問題,為了解決這個問題,就是把這些驅動模塊放到 initrd 或 initramfs 文件中,���啟動器將其載入內存,然後內核加載內存中的驅動模塊,再驅動其它的文件系統,然後進行更多的工作。同時,對於很多嵌入式操作系統而言,可能載入內存的 initrd 或 initramfs 就是最終的文件系統。第二個問題就是 initrd 文件和 initramfs 文件是什麼格式的,怎麼創建和打開。這個問題有點復雜,且看我下面細細道來。

  其實在 Linux 的歷史中,內存中的文件系統使用的技術還不一樣。在很老的系統中,是將某一塊內存模擬成磁盤,稱之為 RamDisk,這個技術效率不高,為什麼不高呢,那是因為將內存模擬成磁盤後,依然需要像對待磁盤一樣對待它,需要給它創建特定格式的文件系統,讀取或寫入文件的時候還是要用到內核的緩存系統,這樣同一份數據就在內存中存在了兩份,所以很浪費。老系統中使用的 initrd 文件其實就相當於是一個磁盤的鏡像,所以要讀取或寫入它的內容,就需要將它掛在到系統中,然後進行讀寫。

  現在我們用的都是新系統,initrd 已經被 initramfs 取代了,雖然很多系統中仍然用initrd.img作為文件名,其實使用的是 initramfs 技術。initramfs 技術不使用 RamDisk,而是使用 tempfs,也就是復用了內核中的緩存系統,所以 tempfs 中的內容在內存中只存在一份,那就是在內核的緩存中,不僅節約了內存開銷,也提高了效率。那麼 initramfs 文件是什麼格式呢?它就是經過壓縮的 CPIO 格式,只要會cpio,打開它就不是問題。

  其實也不是完全沒有問題,我在研究 Fedora 21 的 initramfs.img 文件時就碰到了困難。如果大家使用cat initramfs.img | cpio -imd將該 CPIO 文件解開,會發現只有少許幾個文件,文件數量和文件大小都遠遠低於我們的預期,如下圖:

  問題究竟出在哪裡呢?這是因為 Fedora 21 采用了最新的 Early User Space 技術。這個問題在網上還暫時搜不到答案,我也是看到解壓出的文件中有一個early_cpio,然後以 early 為關鍵詞去看內核的代碼,才知道的。但是關於該技術的具體信息,我也沒搞懂。不過這不是重點,重點是如何正確地將該文件解包。首先,我找到了 Fedora 21 系統中用來構建 initramfs 文件的工具是 dracut,采用的方法論請看我該系列的第一篇,如下圖:

  然後,我發現 dracut 軟件包中提供的lsinitrd工具可以查看 initramfs 中的內容,而且該工具是一個腳本。所以我就把它打開看了一下,如下圖:

  在這個腳本中,我發現它需要用到一個skipcpio程序,跳過 initramfs 文件的頭部後,再將剩下的部分當成壓縮的 CPIO 文件進行解包。看來,會讀腳本程序有時也很重要,所以我的《Bash腳本編程語言中的美學與哲學》這一篇沒有白寫。最後,解包 initramfs 文件的命令是這樣的:

sudo /usr/lib/dracut/skipcpio initramfs-$(uname -r).img | zcat | cpio -imd

  如下圖:

  接下來,我們就可以愉快地研究/init程序都干些什麼了。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-04/116076p2.htm

Copyright © Linux教程網 All Rights Reserved