<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 19.1 Linux 的開機流程分析 如果想要多重開機,那要怎么安裝系統?如果你的 root 密碼忘記了,那要如何救援?如果你的默認登陸模式為圖形界面,那要如何在開機時直接指定進入純文本模式? 如果你因為 /etc/fstab 設置錯誤,導致無法順利掛載根目錄,那要如何在不重灌的情況下修訂你的 /etc/fstab 讓它變成正常?這些都需要了解開機流程, 那你說,這東西重不重要啊? ### 19.1.1 開機流程一覽 既然開機是很嚴肅的一件事,那我們就來了解一下整個開機的過程吧!好讓大家比較容易發現開機過程里面可能會發生問題的地方,以及出現問題后的解決之道! 不過,由于開機的過程中,那個開機管理程序 (Boot Loader) 使用的軟件可能不一樣,例如目前各大 Linux distributions 的主流為 grub2,但早期 Linux 默認是使用 grub1 或 LILO ,臺灣地區則很多朋友喜歡使用 [spfdisk](http://linux.vbird.org/linux_basic/0140spfdisk.php) 。 但無論如何,我們總是得要了解整個 boot loader 的工作情況,才能了解為何進行多重開機的設置時, 老是聽人家講要先安裝 Windows 再安裝 Linux 的原因~ 假設以個人計算機架設的 Linux 主機為例 (先回到[第零章計算機概論](../Text/index.html)看看相關的硬件常識喔), 當你按下電源按鍵后計算機硬件會主動的讀取 BIOS 或 UEFI BIOS 來載入硬件信息及進行硬件系統的自我測試, 之后系統會主動的去讀取第一個可開機的設備 (由 BIOS 設置的) ,此時就可以讀入開機管理程序了。 開機管理程序可以指定使用哪個核心文件來開機,并實際載入核心到內存當中解壓縮與執行, 此時核心就能夠開始在內存內活動,并偵測所有硬件信息與載入適當的驅動程序來使整部主機開始運行, 等到核心偵測硬件與載入驅動程序完畢后,一個最陽春的操作系統就開始在你的 PC 上面跑了。 主機系統開始運行后,此時 Linux 才會調用外部程序開始準備軟件執行的環境,并且實際的載入所有系統運行所需要的軟件程序哩! 最后系統就會開始等待你的登陸與操作啦!簡單來說,系統開機的經過可以匯整成下面的流程的: 1. [載入 BIOS 的硬件信息與進行自我測試,并依據設置取得第一個可開機的設備;](../Text/index.html#process_1) 2. [讀取并執行第一個開機設備內 MBR 的 boot Loader (亦即是 grub2, spfdisk 等程序);](../Text/index.html#process_2) 3. [依據 boot loader 的設置載入 Kernel ,Kernel 會開始偵測硬件與載入驅動程序;](../Text/index.html#process_3) 4. [在硬件驅動成功后,Kernel 會主動調用 systemd 程序,并以 default.target 流程開機;](../Text/index.html#startup_init) * [systemd 執行 sysinit.target 初始化系統及 basic.target 準備操作系統;](../Text/index.html#startup_sysinit) * [systemd 啟動 multi-user.target 下的本機與服務器服務;](../Text/index.html#startup_runlevel) * [systemd 執行 multi-user.target 下的 /etc/rc.d/rc.local 文件;](../Text/index.html#rc.local) * [systemd 執行 multi-user.target 下的 getty.target 及登陸服務;](../Text/index.html#getty) * [systemd 執行 graphical 需要的服務](../Text/index.html#startup_term) 大概的流程就是上面寫的那個樣子啦,你會發現 systemd 這個家伙占的比重非常重! 所以我們才會在[第十六章的 pstree](../Text/index.html#pstree) 指令中談到這家伙。 那每一個程序的內容主要是在干嘛呢?下面就分別來談一談吧! ### 19.1.2 BIOS, boot loader 與 kernel 載入 我們在第二章曾經談過簡單的開機流程與 MBR 的功能,以及大容量磁盤需要使用的 GPT 分區表格式等。 詳細的數據請再次回到第二章好好的閱讀一下,我們這里為了講解方便起見,將后續會用到的專有名詞先做個綜合解釋: * BIOS:不論傳統 BIOS 還是 UEFI BIOS 都會被簡稱為 BIOS; * MBR:雖然分區表有傳統 MBR 以及新式 GPT,不過 GPT 也有保留一塊相容 MBR 的區塊,因此,下面的說明在安裝 boot loader 的部份, 鳥哥還是簡稱為 MBR 喔!總之,MBR 就代表該磁盤的最前面可安裝 boot loader 的那個區塊就對了! * BIOS, 開機自我測試與 MBR/GPT 我們在[第零章的計算機概論](../Text/index.html)就曾談過計算機主機架構, 在個人計算機架構下,你想要啟動整部系統首先就得要讓系統去載入 BIOS (Basic Input Output System),并通過 BIOS 程序去載入 CMOS 的信息,并且借由 CMOS 內的設置值取得主機的各項硬件設置, 例如 CPU 與周邊設備的溝通頻率啊、開機設備的搜尋順序啊、硬盤的大小與類型啊、 系統時間啊、各周邊總線的是否啟動 Plug and Play (PnP, 隨插即用設備) 啊、 各周邊設備的 I/O 位址啊、以及與 CPU 溝通的 IRQ 岔斷等等的信息。 在取得這些信息后,BIOS 還會進行開機自我測試 (Power-on Self Test, POST) [[1]](#ps1)。 然后開始執行硬件偵測的初始化,并設置 PnP 設備,之后再定義出可開機的設備順序,接下來就會開始進行開機設備的數據讀取了。 由于我們的系統軟件大多放置到硬盤中嘛!所以 BIOS 會指定開機的設備好讓我們可以讀取磁盤中的操作系統核心文件。 但由于不同的操作系統他的文件系統格式不相同,因此我們必須要以一個開機管理程序來處理核心文件載入 (load) 的問題, 因此這個開機管理程序就被稱為 Boot Loader 了。那這個 Boot Loader 程序安裝在哪里呢?就在開機設備的第一個扇區 (sector) 內,也就是我們一直談到的 MBR (Master Boot Record, 主要開機記錄區)。 那你會不會覺得很奇怪啊?既然核心文件需要 loader 來讀取,那每個操作系統的 loader 都不相同, 這樣的話 BIOS 又是如何讀取 MBR 內的 loader 呢?很有趣的問題吧!其實 BIOS 是通過硬件的 INT 13 中斷功能來讀取 MBR 的,也就是說,只要 BIOS 能夠偵測的到你的磁盤 (不論該磁盤是 SATA 還是 SAS 接口),那他就有辦法通過 INT 13 這條信道來讀取該磁盤的第一個扇區內的 MBR 軟件啦![[2]](#ps2)這樣 boot loader 也就能夠被執行啰! ![鳥哥的圖示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鳥哥的圖示") **Tips** 我們知道每顆硬盤的最前面區塊含有 MBR 或 GPT 分區表的提供 loader 的區塊,那么如果我的主機上面有兩顆硬盤的話, 系統會去哪顆硬盤的最前面區塊讀取 boot loader 呢?這個就得要看 BIOS 的設置了。 基本上,我們常常講的“系統的 MBR”其實指的是 **第一個開機設備的 MBR** 才對! 所以,改天如果你要將開機管理程序安裝到某顆硬盤的 MBR 時, 要特別注意當時系統的“第一個開機設備”是哪個,否則會安裝到錯誤的硬盤上面的 MBR 喔!重要重要! * Boot Loader 的功能 剛剛說到 Loader 的最主要功能是要認識操作系統的文件格式并據以載入核心到內存中去執行。 由于不同操作系統的文件格式不一致,因此每種操作系統都有自己的 boot loader 啦!用自己的 loader 才有辦法載入核心文件嘛!那問題就來啦,你應該有聽說過多重操作系統吧?也就是在一部主機上面安裝多種不同的操作系統。 既然你 (1)必須要使用自己的 loader 才能夠載入屬于自己的操作系統核心,而 (2)系統的 MBR 只有一個,那你怎么會有辦法同時在一部主機上面安裝 Windows 與 Linux 呢? 這就得要回到[第七章的磁盤文件系統](../Text/index.html)去回憶一下文件系統功能了。 其實每個文件系統 (filesystem, 或者是 partition) 都會保留一塊開機扇區 (boot sector) 提供操作系統安裝 boot loader , 而通常操作系統默認都會安裝一份 loader 到他根目錄所在的文件系統的 boot sector 上。如果我們在一部主機上面安裝 Windows 與 Linux 后,該 boot sector, boot loader 與 MBR 的相關性會有點像下圖: ![boot loader 安裝在 MBR, boot sector 與操作系統的關系](https://box.kancloud.cn/2016-05-13_5735737c03290.gif)圖19.1.1、boot loader 安裝在 MBR, boot sector 與操作系統的關系 如上圖所示,每個操作系統默認是會安裝一套 boot loader 到他自己的文件系統中 (就是每個 filesystem 左下角的方框),而在 Linux 系統安裝時,你可以選擇將 boot loader 安裝到 MBR 去,也可以選擇不安裝。 如果選擇安裝到 MBR 的話,那理論上你在 MBR 與 boot sector 都會保有一份 boot loader 程序的。 至于 Windows 安裝時,他默認會主動的將 MBR 與 boot sector 都裝上一份 boot loader!所以啦, 你會發現安裝多重操作系統時,你的 MBR 常常會被不同的操作系統的 boot loader 所覆蓋啦! ^_^ 我們剛剛提到的兩個問題還是沒有解決啊!雖然各個操作系統都可以安裝一份 boot loader 到他們的 boot sector 中, 這樣操作系統可以通過自己的 boot loader 來載入核心了。問題是系統的 MBR 只有一個哩! 你要怎么執行 boot sector 里面的 loader 啊?這個我們得要回憶一下[第二章約略提過的 boot loader 的功能了](../Text/index.html#partition_bios_uefi)。boot loader 主要的功能如下: * **提供菜單**:使用者可以選擇不同的開機項目,這也是多重開機的重要功能! * **載入核心文件**:直接指向可開機的程序區段來開始操作系統; * **轉交其他 loader**:將開機管理功能轉交給其他 loader 負責。 由于具有菜單功能,因此我們可以選擇不同的核心來開機。而由于具有控制權轉交的功能,因此我們可以載入其他 boot sector 內的 loader 啦!不過 Windows 的 loader 默認不具有控制權轉交的功能,因此你不能使用 Windows 的 loader 來載入 Linux 的 loader 喔!這也是為啥第二章談到 MBR 與多重開機時,會特別強調先裝 Windows 再裝 Linux 的緣故。 我們將上述的三個功能以下面的圖示來解釋你就看的懂了!(與第二章的圖示也非常類似啦!) ![開機管理程序的菜單功能與控制權轉交功能示意圖](https://box.kancloud.cn/2016-05-13_5735737c13e4a.gif)圖19.1.2、開機管理程序的菜單功能與控制權轉交功能示意圖 如上圖所示,我的 MBR 使用 Linux 的 grub2 這個開機管理程序,并且里面假設已經有了三個菜單, 第一個菜單可以直接指向 Linux 的核心文件并且直接載入核心來開機;第二個菜單可以將開機管理程控權交給 Windows 來管理,此時 Windows 的 loader 會接管開機流程,這個時候他就能夠啟動 windows 了。第三個菜單則是使用 Linux 在 boot sector 內的開機管理程序,此時就會跳出另一個 grub2 的菜單啦!了解了嗎? * 菜單一:MBR(grub2) --&gt; kernel file --&gt; booting * 菜單二:MBR(grub2) --&gt; boot sector(Windows loader) --&gt; Windows kernel --&gt; booting * 菜單三:MBR(grub2) --&gt; boot sector(grub2) --&gt; kernel file --&gt; booting 而最終 boot loader 的功能就是“載入 kernel 文件”啦! * 載入核心偵測硬件與 initramfs 的功能 當我們借由 boot loader 的管理而開始讀取核心文件后,接下來, Linux 就會將核心解壓縮到內存當中, 并且利用核心的功能,開始測試與驅動各個周邊設備,包括儲存設備、CPU、網卡、聲卡等等。 此時 Linux 核心會以自己的功能重新偵測一次硬件,而不一定會使用 BIOS 偵測到的硬件信息喔!也就是說,核心此時才開始接管 BIOS 后的工作了。 那么核心文件在哪里啊?一般來說,他會被放置到 /boot 里面,并且取名為 /boot/vmlinuz 才對! ``` [root@study ~]# ls --format=single-column -F /boot config-3.10.0-229.el7.x86_64 &lt;==此版本核心被編譯時選擇的功能與模塊配置文件 grub/ &lt;==舊版 grub1 ,不需要理會這目錄了! grub2/ &lt;==就是開機管理程序 grub2 相關數據目錄 initramfs-0-rescue-309eb890d3d95ec7a.img &lt;==下面幾個為虛擬文件系統文件!這一個是用來救援的! initramfs-3.10.0-229.el7.x86_64.img &lt;==正常開機會用到的虛擬文件系統 initramfs-3.10.0-229.el7.x86_64kdump.img &lt;==核心出問題時會用到的虛擬文件系統 System.map-3.10.0-229.el7.x86_64 &lt;==核心功能放置到內存位址的對應表 vmlinuz-0-rescue-309eb890d09543d95ec7a* &lt;==救援用的核心文件 vmlinuz-3.10.0-229.el7.x86_64* &lt;==就是核心文件啦!最重要者! ``` 從上表中的特殊字體,我們也可以知道 CentOs 7.x 的 Linux 核心為 3.10.0-229.el7.x86_64 這個版本!為了硬件開發商與其他核心功能開發者的便利, 因此 Linux 核心是可以通過動態載入核心模塊的 (就請想成驅動程序即可),這些核心模塊就放置在 /lib/modules/ 目錄內。 由于模塊放置到磁盤根目錄內 (要記得 /lib 不可以與 / 分別放在不同的 partition !), 因此在開機的過程中核心必須要掛載根目錄,這樣才能夠讀取核心模塊提供載入驅動程序的功能。 而且為了擔心影響到磁盤內的文件系統,因此開機過程中根目錄是以只讀的方式來掛載的喔。 一般來說,非必要的功能且可以編譯成為模塊的核心功能,目前的 Linux distributions 都會將他編譯成為模塊。 因此 USB, SATA, SCSI... 等磁盤設備的驅動程序通常都是以模塊的方式來存在的。 現在來思考一種情況,假設你的 linux 是安裝在 SATA 磁盤上面的,你可以通過 BIOS 的 INT 13 取得 boot loader 與 kernel 文件來開機,然后 kernel 會開始接管系統并且偵測硬件及嘗試掛載根目錄來取得額外的驅動程序。 問題是,核心根本不認識 SATA 磁盤,所以需要載入 SATA 磁盤的驅動程序, 否則根本就無法掛載根目錄。但是 SATA 的驅動程序在 /lib/modules 內,你根本無法掛載根目錄又怎么讀取到 /lib/modules/ 內的驅動程序?是吧!非常的兩難吧!在這個情況之下,你的 Linux 是無法順利開機的! 那怎辦?沒關系,我們可以通過虛擬文件系統來處理這個問題。 虛擬文件系統 (Initial RAM Disk 或 Initial RAM Filesystem) 一般使用的文件名為 /boot/initrd 或 /boot/initramfs ,這個文件的特色是,他也能夠通過 boot loader 來載入到內存中,然后這個文件會被解壓縮并且在內存當中仿真成一個根目錄, 且此仿真在內存當中的文件系統能夠提供一支可執行的程序,通過該程序來載入開機過程中所最需要的核心模塊, 通常這些模塊就是 USB, RAID, LVM, SCSI 等文件系統與磁盤接口的驅動程序啦!等載入完成后, 會幫助核心重新調用 systemd 來開始后續的正常開機流程。 ![BIOS 與 boot loader 及核心載入流程示意圖](https://box.kancloud.cn/2016-05-13_5735737c29901.jpg)圖19.1.3、BIOS 與 boot loader 及核心載入流程示意圖 如上圖所示,boot loader 可以載入 kernel 與 initramfs ,然后在內存中讓 initramfs 解壓縮成為根目錄, kernel 就能夠借此載入適當的驅動程序,最終釋放虛擬文件系統,并掛載實際的根目錄文件系統,就能夠開始后續的正常開機流程。 更詳細的 initramfs 說明,你可以自行使用 man initrd 去查閱看看。 下面讓我們來了解一下 CentOS 7.x 的 initramfs 文件內容有什么吧! ^_^ ``` # 1\. 先來直接看一下 initramfs 里面的內容有些啥數據? [root@study ~]# lsinitrd /boot/initramfs-3.10.0-229.el7.x86_64.img # 首先會調用出 initramfs 最前面文件開始的許多數據介紹,這部份會占用一些容量! Image: /boot/initramfs-3.10.0-229.el7.x86_64.img: 18M ======================================================================== Early CPIO image ======================================================================== drwxr-xr-x 3 root root 0 May 4 17:56 . -rw-r--r-- 1 root root 2 May 4 17:56 early_cpio drwxr-xr-x 3 root root 0 May 4 17:56 kernel drwxr-xr-x 3 root root 0 May 4 17:56 kernel/x86 drwxr-xr-x 2 root root 0 May 4 17:56 kernel/x86/microcode -rw-r--r-- 1 root root 10240 May 4 17:56 kernel/x86/microcode/GenuineIntel.bin ======================================================================== Version: dracut-033-240.el7 Arguments: -f dracut modules: # 開始一堆模塊的載入行為 bash nss-softokn .....(中間省略)..... ======================================================================== drwxr-xr-x 12 root root 0 May 4 17:56 . crw-r--r-- 1 root root 5, 1 May 4 17:56 dev/console crw-r--r-- 1 root root 1, 11 May 4 17:56 dev/kmsg crw-r--r-- 1 root root 1, 3 May 4 17:56 dev/null .....(中間省略)..... lrwxrwxrwx 1 root root 23 May 4 17:56 init -&gt; usr/lib/systemd/systemd .....(中間省略)..... drwxr-xr-x 2 root root 0 May 4 17:56 var/lib/lldpad lrwxrwxrwx 1 root root 11 May 4 17:56 var/lock -&gt; ../run/lock lrwxrwxrwx 1 root root 10 May 4 17:56 var/log -&gt; ../run/log lrwxrwxrwx 1 root root 6 May 4 17:56 var/run -&gt; ../run ======================================================================== # 最后則會列出這個 initramfs 里頭的所有文件!也就是說,這個 initramfs 文件大概存著兩部份, # 先是文件開始宣告的許多文件部份,再來才是真的會被核心取用的全部附加的文件數據! ``` 從上面我們大概知道了這個 initramfs 里頭含有兩大區塊,一個是事先宣告的一些數據,包括 kernel/x86/microcode/GenuineIntel.bin 這些東西。 在這些數據后面,才是真的我們的核心會去讀取的重要文件~如果看一下文件的內容,你會發現到 init 那只程序已經被 systemd 所取代啰!這樣理解否? 好~如果你想要進一步將這個文件解開的話,那得要先將前面的 kernel/x86/microcode/GenuineIntel.bin 之前的文件先去除掉,這樣才能夠順利的解開。 因此,得要這樣進行: ``` # 1\. 先將 /boot 下面的文件進行去除前面不需要的文件開始數據部份。 [root@study ~]# mkdir /tmp/initramfs [root@study ~]# cd /tmp/initramfs [root@study initramfs]# dd if=/boot/initramfs-3.10.0-229.el7.x86_64.img of=initramfs.gz \ &gt; bs=11264 skip=1 [root@study initramfs]# ll initramfs.gz; file initramfs.gz -rw-r--r--. 1 root root 18558166 Aug 24 19:38 initramfs.gz initramfs.gz: gzip compressed data, from Unix, last modified: Mon May 4 17:56:47 2015, max compression # 2\. 從上面看到文件是 gzip 壓縮文件,所以將它解壓縮后,再查閱一下文件的類型! [root@study initramfs]# gzip -d initramfs.gz [root@study initramfs]# file initramfs initramfs: ASCII cpio archive (SVR4 with no CRC) # 3\. 解開后又產生一個 cpio 文件,得要將它用 cpio 的方法解開!加上不要絕對路徑的參數較保險! [root@study initramfs]# cpio -i -d -H newc --no-absolute-filenames &lt; initramfs [root@study initramfs]# ll lrwxrwxrwx. 1 root root 7 Aug 24 19:40 bin -&gt; usr/bin drwxr-xr-x. 2 root root 42 Aug 24 19:40 dev drwxr-xr-x. 12 root root 4096 Aug 24 19:40 etc lrwxrwxrwx. 1 root root 23 Aug 24 19:40 init -&gt; usr/lib/systemd/systemd -rw-r--r--. 1 root root 42263552 Aug 24 19:38 initramfs lrwxrwxrwx. 1 root root 7 Aug 24 19:40 lib -&gt; usr/lib lrwxrwxrwx. 1 root root 9 Aug 24 19:40 lib64 -&gt; usr/lib64 drwxr-xr-x. 2 root root 6 Aug 24 19:40 proc drwxr-xr-x. 2 root root 6 Aug 24 19:40 root drwxr-xr-x. 2 root root 6 Aug 24 19:40 run lrwxrwxrwx. 1 root root 8 Aug 24 19:40 sbin -&gt; usr/sbin -rwxr-xr-x. 1 root root 3041 Aug 24 19:40 shutdown drwxr-xr-x. 2 root root 6 Aug 24 19:40 sys drwxr-xr-x. 2 root root 6 Aug 24 19:40 sysroot drwxr-xr-x. 2 root root 6 Aug 24 19:40 tmp drwxr-xr-x. 7 root root 61 Aug 24 19:40 usr drwxr-xr-x. 3 root root 47 Aug 24 19:40 var # 看吧!上面幾乎就像是一個小型的文件系統根目錄耶!這樣就能讓 kernel 去掛載了! # 4\. 接下來瞧一瞧到底這個小型的文件系統中,systemd 是要以哪個 target 來執行開機呢? [root@study initramfs]# ll usr/lib/systemd/system/default.target lrwxrwxrwx. 1 root root 13 Aug 24 19:40 usr/lib/systemd/system/default.target -&gt; initrd.target # 5\. 最終,讓我們瞧一瞧系統內默認的 initrd.target 相依的所有服務數據吧! [root@study initramfs]# systemctl list-dependencies initrd.target initrd.target ├─dracut-cmdline.service .....(中間省略)..... ├─basic.target │ ├─alsa-restore.service .....(中間省略)..... │ ├─slices.target │ │ ├─-.slice │ │ └─system.slice │ ├─sockets.target │ │ ├─dbus.socket .....(中間省略)..... │ │ └─systemd-udevd-kernel.socket │ ├─sysinit.target │ │ ├─dev-hugepages.mount .....(中間省略)..... │ │ ├─local-fs.target │ │ │ ├─-.mount │ │ │ ├─boot.mount .....(中間省略)..... │ │ └─swap.target │ │ ├─dev-centos-swap.swap .....(中間省略)..... │ │ └─dev-mapper-centos\x2dswap.swap │ └─timers.target │ └─systemd-tmpfiles-clean.timer ├─initrd-fs.target └─initrd-root-fs.target # 依舊通過 systemd 的方式,一個一個的將所有的偵測與服務載入系統中! ``` 通過上面解開 initramfs 的結果,你會知道其實 initramfs 就是一個小型的根目錄,這個小型根目錄里面也是通過 systemd 來進行管理,同時觀察 default.target 的鏈接,會發現其實這個小型系統就是通過 initrd.target 來開機,而 initrd.target 也是需要讀入一堆例如 basic.target, sysinit.target 等等的硬件偵測、核心功能啟用的流程, 然后開始讓系統順利運行。最終才又卸載 initramfs 的小型文件系統,實際掛載系統的根目錄! 此外,initramfs 并沒有包山包海,它僅是帶入開機過程會用到的核心模塊而已。所以如果你在 initramfs 里面去找 modules 這個關鍵字的話, 就可以發現主要的核心模塊大概就是 SCSI、virtio、RAID 等等跟磁盤相關性比較高的模塊就是了!現在由于磁盤大部分都是使用 SATA 這玩意兒, 并沒有 IDE 的格式啰!所以,沒有 initramfs 的話,你的 Linux 幾乎就是不能順利開機的啦!除非你將 SATA 的模塊直接編譯到核心去了! ^_^ 在核心完整的載入后,您的主機應該就開始正確的運行了,接下來,就是要開始執行系統的第一支程序: systemd ! ### 19.1.3 第一支程序 systemd 及使用 default.target 進入開機程序分析 在核心載入完畢、進行完硬件偵測與驅動程序載入后,此時你的主機硬件應該已經準備就緒了 (ready) , 此時核心會主動的調用第一支程序,那就是 systemd 啰。這也是為啥[第十六章的 pstree](../Text/index.html#pstree) 指令介紹時,你會發現 systemd 的 PID 號碼是一號啦。 systemd 最主要的功能就是準備軟件執行的環境,包括系統的主機名稱、網絡設置、語系處理、文件系統格式及其他服務的啟動等。 而所有的動作都會通過 systemd 的默認啟動服務集合,亦即是 /etc/systemd/system/default.target 來規劃。 另外, systemd 已經舍棄沿用多年的 system V 的 runlevel 了喔! * 常見的操作環境 target 與相容于 runlevel 的等級 可以作為默認的操作環境 (default.target) 的主要項目有: multi-user.target 以及 graphical.target 這兩個。當然還有某些比較特殊的操作環境, 包括在第十七章里面談到的 rescue.target, emergency.target, shutdown.target 等等,以及本章在 initramfs 里面談到的 initrd.target 啰! 但是過去的 systemV 使用的是一個稱為 runlevel (執行等級) 的概念來啟動系統的,systemd 為了相容于舊式的 systemV 操作行為, 所以也將 runlevel 與操作環境做個結合喔!你可以使用下面的方式來查詢兩者間的對應: ``` [root@study ~]# ll -d /usr/lib/systemd/system/runlevel*.target &#124; cut -c 28- May 4 17:52 /usr/lib/systemd/system/runlevel0.target -&gt; poweroff.target May 4 17:52 /usr/lib/systemd/system/runlevel1.target -&gt; rescue.target May 4 17:52 /usr/lib/systemd/system/runlevel2.target -&gt; multi-user.target May 4 17:52 /usr/lib/systemd/system/runlevel3.target -&gt; multi-user.target May 4 17:52 /usr/lib/systemd/system/runlevel4.target -&gt; multi-user.target May 4 17:52 /usr/lib/systemd/system/runlevel5.target -&gt; graphical.target May 4 17:52 /usr/lib/systemd/system/runlevel6.target -&gt; reboot.target ``` 如果你之前已經使用過 systemV 的方式來管理系統的話,那應該會知道切換執行等級可以使用“ init 3 ”轉成文字界面,“ init 5 ”轉成圖形界面吧? 這個 init 程序依舊是保留下來的,只是 init 3 會相當于 systemctl isolate multi-user.target 就是了!如果做個完整的疊代,這兩個東西的對應為: | SystemV | systemd | | --- | --- | | init 0 | systemctl poweroff | | init 1 | systemctl rescue | | init [234] | systemctl isolate multi-user.target | | init 5 | systemctl isolate graphical.target | | init 6 | systemctl reboot | * systemd 的處理流程 如前所述,當我們取得了 /etc/systemd/system/default.target 這一個默認操作界面的設置之后,接下來系統幫我們做了什么呢? 首先,它會鏈接到 /usr/lib/systemd/system/ 這個目錄下去取得 multi-user.target 或 graphical.target 這兩個其中的一 (當然, 鳥哥說的是正常的進入 Linux 操作環境的情況下!),假設我們是使用 graphical.target 好了,接著下來 systemd 會去找兩個地方的設置, 就是如下的目錄: * /etc/systemd/system/graphical.target.wants/:使用者設置載入的 unit * /usr/lib/systemd/system/graphical.target.wants/:系統默認載入的 unit 然后再由 /usr/lib/systemd/system/graphical.target 這個配置文件內發現如下的數據: ``` [root@study ~]# cat /usr/lib/systemd/system/graphical.target [Unit] Description=Graphical Interface Documentation=man:systemd.special(7) Requires=multi-user.target After=multi-user.target Conflicts=rescue.target Wants=display-manager.service AllowIsolate=yes [Install] Alias=default.target ``` 這表示 graphical.target 必須要完成 multi-user.target 之后才能夠進行,而進行完 graphical.target 之后,還得要啟動 display-manager.service 才行的意思。 好了!那么通過同樣的方式,我們來找找 multi-user.target 要執行完畢得要載入的項目有哪些呢? ``` # 先來看看 multi-user.target 配置文件內規范了相依的操作環境有哪些呢? [root@study ~]# cat /usr/lib/systemd/system/multi-user.target [Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes [Install] Alias=default.target # 然后看看系統默認要載入的 unit 有哪些? [root@study ~]# ls /usr/lib/systemd/system/multi-user.target.wants brandbot.path plymouth-quit.service systemd-logind.service dbus.service plymouth-quit-wait.service systemd-user-sessions.service getty.target systemd-ask-password-wall.path # 使用者自訂要載入的 unit 又有哪些呢? [root@study ~]# ls /etc/systemd/system/multi-user.target.wants abrt-ccpp.service crond.service mdmonitor.service sshd.service abrtd.service hypervkvpd.service ModemManager.service sysstat.service abrt-oops.service hypervvssd.service NetworkManager.service tuned.service abrt-vmcore.service irqbalance.service postfix.service vmtoolsd.service abrt-xorg.service kdump.service remote-fs.target vsftpd2.service atd.service ksm.service rngd.service vsftpd.service auditd.service ksmtuned.service rsyslog.service backup2.timer libstoragemgmt.service smartd.service backup.timer libvirtd.service sshd2.service ``` 通過上面的結果,我們又能知道 multi-usre.target 需要在 basic.target 運行完畢才能夠載入上述的許多 unit 哩!然后再去 basic.target 里頭找數據等等~ 最終這些數據就可以通過“ systemctl list-dependencies graphical.target ”這個指令來列出所有的相關性的服務啰!這就是 systemd 的調用所需要的服務的流程喔! ![鳥哥的圖示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鳥哥的圖示") **Tips** 要知道系統的服務啟用的流程,最簡單的方法就是“ systemctl list-dependencies graphical.target ”這個指令!只是,如果你想要知道背后的配置文件意義, 那就是分別去找出 /etc 與 /usr/lib 下面的 graphical.target.wants/ 目錄下的數據就對了!當然,配置文件腳本里面的 Requires 這個設置值所代表的服務, 也是需要是先載入喔! 約略分析一下“ systemctl list-dependencies graphical.target ”所輸出的相依屬性服務,基本上我們 CentOS 7.x 的 systemd 開機流程大約是這樣: 1. local-fs.target + swap.target:這兩個 target 主要在掛載本機 /etc/fstab 里面所規范的文件系統與相關的內存交換空間。 2. sysinit.target:這個 target 主要在偵測硬件,載入所需要的核心模塊等動作。 3. basic.target:載入主要的周邊硬件驅動程序與防火墻相關任務 4. multi-user.target 下面的其它一般系統或網絡服務的載入 5. 圖形界面相關服務如 gdm.service 等其他服務的載入 除了第一步驟 local-fs.target, swap.target 是通過 /etc/fstab 來進行掛載的行為之外,那其他的 target 有做啥動作呢?簡單得來說說! ### 19.1.4 systemd 執行 sysinit.target 初始化系統、basic.target 準備系統 如果你自己使用“ systemctl list-dependencies sysinit.target ”來瞧瞧的話,那就會看到很多相依的服務!這些服務你應該要一個一個去查詢看看設置腳本的內容, 就能夠大致理解每個服務的意義。基本上,我們可以將這些服務歸類成幾個大項就是了: * 特殊文件系統設備的掛載:包括 dev-hugepages.mount dev-mqueue.mount 等掛載服務,主要在掛載跟巨量內存分頁使用與訊息佇列的功能。 掛載成功后,會在 /dev 下面創建 /dev/hugepages/, /dev/mqueue/ 等目錄; * 特殊文件系統的啟用:包括磁盤陣列、網絡磁盤 (iscsi)、LVM 文件系統、文件系統對照服務 (multipath) 等等,也會在這里被偵測與使用到! * 開機過程的訊息傳遞與動畫執行:使用 plymouthd 服務搭配 plymouth 指令來傳遞動畫與訊息 * 日志式登錄文件的使用:就是 systemd-journald 這個服務的啟用啊! * 載入額外的核心模塊:通過 /etc/modules-load.d/*.conf 文件的設置,讓核心額外載入管理員所需要的核心模塊! * 載入額外的核心參數設置:包括 /etc/sysctl.conf 以及 /etc/sysctl.d/*.conf 內部設置! * 啟動系統的亂數產生器:亂數產生器可以幫助系統進行一些密碼加密演算的功能 * 設置終端機 (console) 字形 * 啟動動態設備管理員:就是 udevd 這個家伙!用在動態對應實際設備存取與設備文件名對應的一個服務!相當重要喔!也是在這里啟動的! 不論你即將使用哪種操作環境來使用系統,這個 sysinit.target 幾乎都是必要的工作!從上面你也可以看的出來,基本的核心功能、文件系統、文件系統設備的驅動等等, 都在這個時刻處理完畢~所以,這個 sysinit.target 的階段是挺重要的喔! 執行完 sysinit.target 之后,再來則是 basic.target 這個項目了。 sysinit.target 在初始化系統,而這個 basic .target 則是一個最陽春的操作系統了! 這個 basic.target 的階段主要啟動的服務大概有這些: * 載入 alsa 音效驅動程序:這個 alsa 是個音效相關的驅動程序,會讓你的系統有音效產生啰; * 載入 firewalld 防火墻:CentOS 7.x 以后使用 firewalld 取代 iptables 的防火墻設置,雖然最終都是使用 iptables 的架構, 不過在設置上面差很多喔! * 載入 CPU 的微指令功能; * 啟動與設置 SELinux 的安全本文:如果由 disable 的狀態改成 enable 的狀態,或者是管理員設置強制重新設置一次 SELinux 的安全本文, 也在這個階段處理喔! * 將目前的開機過程所產生的開機信息寫入到 /var/log/dmesg 當中 * 由 /etc/sysconfig/modules/*.modules 及 /etc/rc.modules 載入管理員指定的模塊! * 載入 systemd 支持的 timer 功能; 在這個階段完成之后,你的系統已經可以順利的運行!就差一堆你需要的登陸服務、網絡服務、本機認證服務等等的 service 類別啰!于是就可以進入下個服務啟動的階段了! ### 19.1.5 systemd 啟動 multi-user.target 下的服務 在載入核心驅動硬件后,經過 sysinit.target 的初始化流程讓系統可以存取之后,加上 basic.target 讓系統成為操作系統的基礎, 之后就是服務器要順利運行時,需要的各種主機服務以及提供服務器功能的網絡服務的啟動了。這些服務的啟動則大多是附掛在 multi-user.target 這個操作環境下面, 你可以到 /etc/systemd/system/multi-user.target.wants/ 里頭去瞧瞧默認要被啟動的服務喔! 也就是說,一般來說服務的啟動腳本設置都是放在下面的目錄內: * /usr/lib/systemd/system (系統默認的服務啟動腳本設置) * /etc/systemd/system (管理員自己開發與設置的腳本設置) 而使用者針對主機的本機服務與服務器網絡服務的各項 unit 若要 enable 的話,就是將它放到 /etc/systemd/system/multi-user.target.wants/ 這個目錄下面做個鏈接~ 這樣就可以在開機的時候去啟動他。這時回想一下,你在第十七章使用 systemctl enable/disable 時,系統的回應是什么呢?再次回想一下: ``` # 將 vsftpd.service 先 disable 再 enable 看看輸出的信息為何? [root@study ~]# systemctl disable vsftpd.service rm '/etc/systemd/system/multi-user.target.wants/vsftpd.service' [root@study ~]# systemctl enable vsftpd.service ln -s '/usr/lib/systemd/system/vsftpd.service' '/etc/systemd/system/multi-user.target. wants/vsftpd.service' ``` 有沒有發現亮點了?不是從 /etc/systemd/system/multi-user.target.wants/ 里面刪除鏈接文件,就是創建鏈接文件~這樣說,理解吧? 你當然不需要手動作這些鏈接,而是使用 systemctl 來處理即可!另外,這些程序除非在腳本設置里面原本就有規范服務的相依性, 這樣才會有順序的啟動之外,大多數的服務都是同時啟動的!這就是 systemd 的多任務啰。 * 相容 systemV 的 rc-local.service 另外,過去用過 Linux 的朋友大概都知道,當系統完成開機后,還想要讓系統額外執行某些程序的話,可以將該程序指令或腳本的絕對路徑名稱寫入到 /etc/rc.d/rc.local 這個文件去!新的 systemd 機制中,它建議直接寫一個 systemd 的啟動腳本配置文件到 /etc/systemd/system 下面,然后使用 systemctl enable 的方式來設置啟用它,而不要直接使用 rc.local 這個文件啦! 但是像鳥哥這種老人家就是喜歡將開機后要立刻執行的許多管理員自己的腳本,將它寫入到 /etc/rc.d/rc.local 去嘛!那新版的 systemd 有沒有支持呢? 當然有!那就是 rc-local.service 這個服務的功能了!這個服務不需要啟動,它會自己判斷 /etc/rc.d/rc.local 是否具有可執行的權限來判斷要不要啟動這個服務! 你可以這樣檢查看看: ``` # 1\. 先看一下 /etc/rc.d/rc.local 的權限,然后檢查 multi-user.target 有沒有這個服務 [root@study ~]# ll /etc/rc.d/rc.local -rw-r--r--. 1 root root 473 Mar 6 13:48 /etc/rc.d/rc.local [root@study ~]# systemctl status rc-local.service rc-local.service - /etc/rc.d/rc.local Compatibility Loaded: loaded (/usr/lib/systemd/system/rc-local.service; static) Active: inactive (dead) [root@study ~]# systemctl list-dependencies multi-user.target &#124; grep rc-local # 明明就有這個服務,但是 rc.local 不具有可執行 (x) 的權限,因此這個服務不會被執行 # 2\. 加入可執行權限后,再看一下 rc-local 是否可被啟用! [root@study ~]# chmod a+x /etc/rc.d/rc.local; ll /etc/rc.d/rc.local -rwxr-xr-x. 1 root root 473 Mar 6 13:48 /etc/rc.d/rc.local [root@study ~]# systemctl daemon-reload [root@study ~]# systemctl list-dependencies multi-user.target &#124; grep rc-local ├─rc-local.service # 這個服務確實被記錄到啟動的環境下啰! ``` 通過這個 chmod a+x /etc/rc.d/rc.local 的步驟,你的許多腳本就可以放在 /etc/rc.d/rc.local 這個文件內, 系統在每次開機都會去執行這文件內的指令喔!非常簡單吧! * 提供 tty 界面與登陸的服務 在 multi-user.target 下面還有個 getty.target 的操作界面項目喔! 這個項目就是我們在[第十七章用來舉例的 tty 終端機界面的個數案例](../Text/index.html#systemd_cfg_repeat)。 能不能提供適當的登陸服務也是 multi-user.target 下面的內容!包括 systemd-logind.service, systemd-user-sessions.service 等服務。 比較有趣的地方是,由于服務都是同步運行,不一定哪個服務先啟動完畢。如果 getty 服務先啟動完畢時,你會發現到有可用的終端機嘗試讓你登陸系統了。 問題是,如果 systemd-logind.service 或 systemd-user-sessions.service 服務尚未執行完畢的話,那么你還是無法登陸系統的。 ![鳥哥的圖示](https://box.kancloud.cn/2016-05-13_5735736501917.gif "鳥哥的圖示") **Tips** 有些比較急性子的伙伴在啟動 CentOS 7.x 時,看到屏幕出現 tty1 可以讓他登陸了~但是一開始輸入正確的帳密卻無法登陸系統! 總要隔了數十秒之后才能夠順利的登陸!知道原因了嗎? ^_^ ### 19.1.6 systemd 啟動 graphical.target 下面的服務 如果你的 default.target 是 multi-user.target 的話,那么這個步驟就不會進行。反之,如果是 graphical.target 的話,那么 systemd 就會開始載入用戶管理服務與圖形界面管理員 (window display manager, DM) 等,啟動圖形界面來讓用戶以圖形界面登陸系統喔! 如果你對于 graphical.target 多了哪些服務有興趣,那就來檢查看看: ``` [root@study ~]# systemctl list-dependencies graphical.target graphical.target ├─accounts-daemon.service ├─gdm.service ├─network.service ├─rtkit-daemon.service ├─systemd-update-utmp-runlevel.service └─multi-user.target ├─abrt-ccpp.service .....(下面省略)..... ``` 事實上就是多了上面列出來的這些服務而已~大多數都是圖形界面帳號管理的功能,至于實際讓用戶可以登陸的服務,倒是那個 gdm.service 哩! 如果你去瞧瞧 gdm.service 的內容,就會發現最重要的可執行文件是 /usr/sbin/gdm 喔!那就是讓使用者可以利用圖形界面登陸的最重要服務啰! 我們未來講到 X 窗口界面時再來聊聊 gdm 這玩意兒喔! 到此為止,systemd 就已經完整的處理完畢,你可以使用圖形界面或文字界面的方式來登陸系統,系統也順利的開機完畢, 也能夠將你寫入到 /etc/rc.d/rc.local 的腳本實際執行一次啰。那如果默認是圖形界面 (graphical.target) 但是想要關掉而進入文字界面 (multi-user.target) 呢? 很簡單啊!19.1.3小節就談過了,使用“ systemctl isolate multi-user.target ”即可!如果使用“ init 3 ”呢?也是可以啦! 只是系統實際執行的還是“ systemctl isolate multi-user.target ”就是了! ^_^ ### 19.1.7 開機過程會用到的主要配置文件 基本上, systemd 有自己的配置文件處理方式,不過為了相容于 systemV ,其實很多的服務腳本設置還是會讀取位于 /etc/sysconfig/ 下面的環境配置文件! 下面我們就來談談幾個常見的比較重要的配置文件啰! * 關于模塊: /etc/modprobe.d/*.conf 及 /etc/modules-load.d/*.conf 還記得我們在 [sysinit.target 系統初始化](../Text/index.html#startup_sysinit) 當中談到的載入使用者自訂模塊的地方嗎?其實有兩個地方可以處理模塊載入的問題,包括: * /etc/modules-load.d/*.conf:單純要核心載入模塊的位置; * /etc/modprobe.d/*.conf:可以加上模塊參數的位置 基本上 systemd 已經幫我們將開機會用到的驅動程序全部載入了,因此這個部份你應該無須更動才對!不過, 如果你有某些特定的參數要處理時,應該就得要在這里進行了。舉例來說,我們在第十七章曾經談過 vsftpd 這個服務對吧! 而且當時將這個服務的端口更改到 555 這個號碼上去了!那我們可能需要修改防火墻設置,其中一個針對 FTP 很重要的防火墻模塊為 nf_conntrack_ftp, 因此,你可以將這個模塊寫入到系統開機流程中,例如: ``` [root@study ~]# vim /etc/modules-load.d/vbird.conf nf_conntrack_ftp ``` 一個模塊 (驅動程序) 寫一行~然后,上述的模塊基本上是針對默認 FTP 端口,亦即 port 21 所設置的,如果需要調整到 port 555 的話, 得要外帶參數才行!模塊外加參數的設置方式得要寫入到另一個地方喔! ``` [root@study ~]# vim /etc/modprobe.d/vbird.conf options nf_conntrack_ftp ports=555 ``` 之后重新開機就能夠順利的載入并且處理好這個模塊了。不過,如果你不想要開機測試,想現在處理呢?有個方式可以來進行看看: ``` [root@study ~]# lsmod &#124; grep nf_conntrack_ftp # 沒東西!因為還沒有載入這個模塊!所以不會出現任何訊息! [root@study ~]# systemctl restart systemd-modules-load.service [root@study ~]# lsmod &#124; grep nf_conntrack_ftp nf_conntrack_ftp 18638 0 nf_conntrack 105702 1 nf_conntrack_ftp ``` 通過上述的方式,你就可以在開機的時候將你所需要的驅動程序載入或者是調整這些模塊的外加參數啰! * /etc/sysconfig/* 還有哪些常見的環境配置文件呢?我們找幾個比較重要的來談談: * authconfig: 這個文件主要在規范使用者的身份認證的機制,包括是否使用本機的 /etc/passwd, /etc/shadow 等, 以及 /etc/shadow 密碼記錄使用何種加密演算法,還有是否使用外部密碼服務器提供的帳號驗證 (NIS, LDAP) 等。 系統默認使用 SHA512 加密演算法,并且不使用外部的身份驗證機制;另外,不建議手動修改這個文件喔!你應該使用“ authconfig-tui ”指令來修改較佳! * cpupower: 如果你有啟動 cpupower.service 服務時,他就會讀取這個配置文件。主要是 Linux 核心如何操作 CPU 的原則。 一般來說,啟動 cpupower.service 之后,系統會讓 CPU 以最大性能的方式來運行,否則默認就是用多少算多少的模式來處理的。 * firewalld, iptables-config, iptables-config, ebtables-config: 與防火墻服務的啟動外帶的參數有關,這些數據我們會在服務器篇慢慢再來討論。 * network-scripts/: 至于 network-scripts 里面的文件,則是主要用在設置網卡~ 這部份我們在[服務器架設篇](http://linux.vbird.org/linux_server)才會提到!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看