天天看點

開機流程,子產品管理與loader0.0

Linux開機流程

Linux執行的時候,雖然沒有任何畫面,但其實有很多的程式在背景底下執行的,例如登入檔案程控程式,例行性工作安排,還有一大堆網絡服務,郵件伺服器,www伺服器

如果不正常關機将會導緻傷害硬碟及資料傳輸的動作

開機中用到的那個開機管理程式(Boot Loader)使用的軟體可能不一樣,大多數的Linux distributions使用的是grub,早期的LILO,spfdisk

系統開機的大緻經過:

1 加載BIOS的硬體資訊與進行自我測試,并依據設定取得第一個可開機的裝置(BIOS程式加載CMOS的資訊,并根據CMOS内的設定值取得主機的各項硬體配置)

2 讀取并執行第一個開機裝置内MBR的boot Loader(也就是grub, spfdisk等程式)(由于不同的作業系統的檔案格式不同,此時需要有一個開機管理程式處理核心加載的問題)

3 依據boot loader的設定加載kernel,kernel會開始偵測硬體與加載驅動程式(BIOS是通過硬體的INT13功能讀取磁盤的第一個扇區内的MBR,這樣boot loader就能被執行)

4 在硬體驅動成功後,kernel會主動呼叫init程式,而init會取得run-level資訊

5 init執行/etc/rc.d/rc.sysinit 檔案來準備軟體啟動執行的環境

6 init 執行run-level的各個服務之啟動(script方式)

7 init執行/etc/rc.d/rc.local 檔案

8 init執行終端機仿真程式mingetty來啟動login程式 最後等待使用者登入

BootLoader的功能

Loader的功能是要認識作業系統的檔案格式并加載核心到主存儲器中去執行,由于不同作業系統的檔案格式不一緻,是以每種作業系統都有自己的boot loader,loader才有辦法

載入核心檔案,那系統隻有一個MBR,如何安裝多個作業系統呢?其實每個檔案系統都會保留一塊啟動扇區提供作業系統安裝boot loader ,而通常作業系統預設都會安裝一份

loader到根目錄所在的檔案系統的boot sector上

每個作業系統預設會安裝一套boot loader到他自己的檔案系統中(每個filesystem左下角的方框),linux系統安裝時,你可以選擇boot loader安裝到MBR去,也可以選擇不安裝

如果選擇安裝到MBR的話,那理論上你在MBR與boot sector都會保有一份boot loader,這樣作業系統可以透過自己的boot loader來加載核心,問題是系統的MBR隻有一個

怎麼才能執行boot sector中boot loader呢?

提供選單:使用者可以選擇不同的開機項目,這也是多重引導的重要功能!

載入核心檔案:直接指向可開機的程式區段來開始作業系統;

轉交其他 loader:将開機管理功能轉交給其他 loader 負責。

由于具有選單功能,我們可以選擇不同的核心來開機,由于具有控制權轉交的功能,是以我們可以加載其他boot sector内的loader,不過Windows的loader不具有控制權轉交

的功能,是以不能使用windows的loader來加載linux的loader

我們MBR使用Linux的grub這個開機管理程式,裡面有三個選單,第一個直接指向Linux的核心檔案并且直接加載核心來開機,第二個可以将管理權交給windows來管理

此時windows的load會接管開機流程,第三個使用linux在boot sector内的開機管理程式,此時會跳出另一個grub的選單啦,最終boot loader的功能就是加載kernel檔案

加載後将核心解壓縮到主存儲器中,并且利用核心的功能,開始測試與驅動各個周邊裝置,包括儲存裝置,CPU,網絡卡,等等,linux核心重新偵測一次硬體,而不一定

使用BIOS偵測到的硬體資訊,此時核心開機接管BIOS的工作,核心檔案被放置到/boot裡面,取名為/boot/vmlinuz

ls --format=single-column -F /boot

config-2.6.18-92.el5 <==此版本核心被編譯時選擇的功能與子產品配置檔案

grub/ <==就是開機管理程式 grub 相關資料目錄

initrd-2.6.18-92.el5.img <==虛拟檔案系統檔!

System.map-2.6.18-92.el5 <==核心功能放置到記憶體位址的對應表

vmlinuz-2.6.18-92.el5 <==就是核心檔案啦!最重要者!

Linux核心是可以透過動态加載核心子產品(相當于驅動程式),這些核心子產品放置在/lib/modules/目錄内,/lib與/ 一定要在一個檔案系統中,不能放在不同partition,是以開機時

核心必須要挂載根目錄,這樣才能夠讀取核心子產品提供加載驅動程式的功能,為了擔心影響到磁盤内的檔案系統,是以開機過程中目錄是以隻讀的方式來挂載的

一般來說,非必要的功能可以編譯成為子產品的核心功能,Linux distribution都會将他編譯成為子產品,是以USB,SATA SCSI等磁盤裝置的驅動程式通常都是以子產品的方式來存在的

假設linux安裝在SATA磁盤上面,通過BIOS的INT13取得boot loader 與kernel,接着kernel嘗試挂載根目錄來取得額外的驅動程式,由于核心不認識SATA磁盤,是以需要驅動

程式,而驅動程式則是在/lib/modules内,根本無法挂載根目錄,也就無法取得/lib/modules/ 内的驅動程式,這種情況下,可以通過虛拟檔案系統來處理這個問題

虛拟檔案系統 (Initial RAM Disk) 一般使用的檔名為 /boot/initrd,這個檔案的特色是,他也能夠透過 boot loader 來加載到記憶體中,然後這個檔案會被觋壓縮幵丏在記憶體

當中仿真成一個根目錄, 且此仿真在記憶體當中的檔案系統提供一支可執行的程式,透過該程式來加載開機過程中所需要的核心子產品,通常這些子產品就是USB,RAID,LVM,SCSI

等檔案系統與磁盤接口的驅動程式,等載入完成後,會幫助核心重新呼叫/sbin/init 來開始後續的正常開機流程.

boot loader 可以加載 kernel 不 initrd,然後在記憶體中讓 initrd 解壓縮成為根目錄,kernel 就能夠藉此加載适當的驅劢程式,最終釋放虛拟檔案系統,幵挂載實際的根目錄檔案

系統

initrd檔案的内容:

file initramfs-2.6.32-279.el6.x86_64.img 檢視到原來是gzip的壓縮檔案,因為是gzip,

是以擴充名改為.gz    mv initrd-2.6.18-92.el5.img initrd-2.6.18-92.el5.gz

接着解壓縮  gzip -d initrd-2.6.18-92.el5.gz

再次檢視檔案類型  file initramfs-2.6.32-279.el6.x86_64  原來是cpio的指令壓縮成的檔案

再次解壓縮  cpio -ivcdu < initrd-2.6.18-92.el5

可以看出這個檔案中的内容和根目錄很像,尤其也是有init這個執行檔,檢視init執行檔中的檔案内容

 cat init

mount -t proc /proc /proc    <==挂載記憶體的虛拟檔案系統

mknod /dev/null c 1 3  <==建立系統所需要的各項裝置!

insmod /lib/ehci-hcd.ko   <==加載各項核心子產品,就是驅動程式!

mkrootdev -t ext3 -o defaults,ro hdc2 <==嘗試挂載根目錄!

由上面的内容我們知道initrd有加載子產品并且嘗試挂載了虛拟檔案系統,接下來能夠順利的運作,那麼是否一定需要initrd

需要initrd最重要的原因是,當開機時無法挂載根目錄的情況下,此時需要initrd ,例如你的根目錄在特殊的磁盤接口

USB SATA SCSI 或者是你的檔案系統位特殊(LVM RAID)等等,才需要initrd,但是如果你的LInux安裝在IDE接口的磁盤上

并且預設使用的是ext2或ext3檔案系統,那麼不需要initrd也能夠順利的開機進入Linux的

核心加載完畢, 進行完硬體偵測和驅動完整的加載後,接下來開始執行系統的第一支程式 /sbin/init,init的PID号碼是一号

/sbin/init 最主要的功能就是準備軟體執行的環境,包括系統的主機名,網絡設定,語系處理,檔案系統格式以及其他服務的

啟動,而所有的動作都會透過init的配置檔案,也就是/etc/inittab來規劃,而inittab還有一個重要的設定,就是預設的runlevel

(開機執行等級)

id:5:initdefault:   <==預設的 runlevel 設定, 此 runlevel 為 5

si::sysinit:/etc/rc.d/rc.sysinit <==準備系統軟體執行的環境的腳本執行檔

l0:0:wait:/etc/rc.d/rc 0 <==runlevel 0 在 /etc/rc.d/rc0.d/

l1:1:wait:/etc/rc.d/rc 1 <==runlevel 1 在 /etc/rc.d/rc1.d/

l2:2:wait:/etc/rc.d/rc 2 <==runlevel 2 在 /etc/rc.d/rc2.d/

l3:3:wait:/etc/rc.d/rc 3 <==runlevel 3 在 /etc/rc.d/rc3.d/

l4:4:wait:/etc/rc.d/rc 4 <==runlevel 4 在 /etc/rc.d/rc4.d/

l5:5:wait:/etc/rc.d/rc 5 <==runlevel 5 在 /etc/rc.d/rc5.d/

 l6:6:wait:/etc/rc.d/rc 6 <==runlevel 6 在 /etc/rc.d/rc6.d/

是否允許按下 [ctrl]+[alt]+[del] 就重新啟動的設定項目:  ca::ctrlaltdel:/sbin/shutdown -t3 -r now

# 底下兩個讴定則是關亍丌斷電系統的 (UPS),一個是沒電力時的關機,一個是複電的處理

pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"

pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown  Cancelled"

1:2345:respawn:/sbin/mingetty tty1 <==其實 tty1~tty6 是由底下這六行決定的

2:2345:respawn:/sbin/mingetty tty2

3:2345:respawn:/sbin/mingetty tty3

4:2345:respawn:/sbin/mingetty tty4

5:2345:respawn:/sbin/mingetty tty5

6:2345:respawn:/sbin/mingetty tty6

x:5:respawn:/etc/X11/prefdm -nodaemon <==X window 則是這行決定的!

init 的動作項目:主要可以進行的動作項目意義有:

initdefault 代表預設的 run level 設定值

sysinit  代表系統初始化的動作項目

ctrlaltdel  代表 [ctrl]+[alt]+[del] 三個按鍵是否可以重新啟動的設定

wait 代表後面字段設定的指令項目必須要執行完畢才能繼續底下其他的動作

respawn  代表後面字段的指令可以無限制的再生 (重新啟動)

舉例來說, tty1 的 mingetty産生的可登入畫面,在你登出而結束後,系統會再開一個新的可登入畫面等待下一個登入

init的作用

1. 先取得 runlevel 亦即預設執行等級的相關等級  通常預設都是 3 或 5來作為預設的run level的,但有時需要進入run level 1,也就是單人維護模式

2. 使用 /etc/rc.d/rc.sysinit 進行系統環境初始化

3. 由亍 runlevel 是 5 ,是以隻進行『l5:5:wait:/etc/rc.d/rc 5』,其他行則略過

4. 設定好 [ctrl]+[alt]+[del] 這組的組合鍵功能

5. 設定不斷電系統的 pf, pr 兩種機制;

6. 啟動 mingetty 的六個終端機 (tty1 ~ tty6)  如果不想要啟動六個終端機,那麼可以将 6:2345:respawn:/sbin/mingettytty6』關閉數個。但務必至少激活一個

7. 最終以 /etc/X11/perfdm -nodaemon 啟動圖形接口啦!

在init 取得run level後,接下來處理系統初始化流程 /etc/rc.d/rc.sysinit 表示在加載各項系統服務之前,得先做好整個系統環境,主要利用/etc/rc.d/rc.sysinit

這個shell script來設定好我的系統環境,接着描述sysinit主要的工作項目:

1 取得網絡環境不主機類型: 讀取/etc/sysconfig/network 等網絡環境設定

2 測試與挂載記憶體裝置/proc 以及一些USB裝置 /sys

3 決定是否啟動 SELinux

4 啟動系統的随機數生成器 随機數生成器可以幫助系統進行一些密碼加密演算的功能,在此需要啟動兩次随機數生成器

5 設定終端機字形

6 設定顯示亍開機過程中的歡迎畫面 (text banner);

7 設定系統時間 (clock) 與時區設定:需讀入 /etc/sysconfig/clock 設定值

8 接口裝置的偵測與 Plug and Play (PnP) 參數的測試:根據核心在開機時偵測的結果  (/proc/sys/kernel/modprobe ) 開始進行 ide / scsi / 網絡 / 音效等接口裝置的偵測,

以及利用以加載的核心子產品進行 PnP 裝置的參數測試

9 使用者自定義子產品的加載  使用者可以在 /etc/sysconfig/modules/*.modules 加入自定義的子產品,則此時會被加載到系統當中

10. 加載核心的相關設定:系統會主動去讀取 /etc/sysctl.conf 這個檔案的設定值,使核心功能成為我們想要的樣子。

11. 設定主機名與初始化電源管理子產品 (ACPI)

12. 初始化軟體磁盤陣列:主要是透過 /etc/mdadm.conf 來設定好的。

13. 初始化 LVM 的檔案系統功能

14. 以 fsck 檢驗磁盤檔案系統:會進行 filesystem check

15. 進行磁盤配額 quota 的轉換 (非必要):

16. 重新以可擦寫模式挂載系統磁盤:

17. 啟動 quota 功能:是以我們不需要自定義 quotaon 的動作

18. 啟動系統虛拟随機數生成器 (pseudo-random):

19. 清除開機過程當中的臨時檔案:

20. 将開機相關資訊加載 /var/log/dmesg 檔案中

rc.sysinit将基本的系統設定資料都寫好了,也将系統的資料設定完整,如果想了解開機過程發生了什麼,執行dmesg把,在這個檔案中所進行的

很多預設配置檔案,其實都是在/etc/sysconfig/當中

如果想要加載核心子產品的話,可以将子產品寫入到/etc/sysconfig/module/*.modules當中,隻要記得以.modules結尾即可,其實目前的預設子產品

已經夠用了,除非你的主機硬體實在太新了,非要自己加載新的子產品不可,否則在經過rc.sysinit處理後,你的主機應該可以跑得很順暢了

接着就等着你将系統相關的服務與網絡服務啟動

run level要執行的各項腳本放置處是 /etc/rc.d/目錄下,主要是夠過/etc/rc.d/rc這個指令來處理相關任務,如果預設是5的話,那麼就取對應的rc 5這個目錄

我們先看/etc/rc.d/rc這個檔案

透過外部第一号參數($1)來取得想要執行的腳本目錄,也就是指/etc/rc.d/rc 5,可以取得/etc/rc5.d/這個目錄來準備處理相關的腳本程式

找到 /etc/rc5.d/K??* 開頭的檔案 并進行/etc/rc5.d/K??* stop

找到 /etc/rc5.d/S??* 開頭的檔案 并進行/etc/rc5.d/S??* start

檢視rc5.d/這個目錄的内容,這個目錄下的所有檔案都是以Sxx或Kxx 全部都是連結檔,連結到stand alone服務啟動的目錄/etc/init.d/去

可以看出 /etc/rc5.d/[SK]xx 就是/etc/init.d目錄下去找對應的服務腳本,然後分别進行start和stop的動作而已

例如表格内的 K91capi 及 S10network 為例好了,透過/etc/rc.d/rc 5的執行

/etc/rc5.d/K91capi stop --> /etc/init.d/capi stop

/etc/rc5.d/S10network start --> /etc/init.d/network start

是以想要啟動該runlevel時就啟動執行的服務,那麼利用Sxx指向/etc/init.d/的特定服務啟動腳本後,該服務就能夠在開機時啟動了,chkconfig就是負責

處理這個連結檔的指令,那麼K與S後面的數字表示各個不同的服務其實還是互有關系的,例如想要啟動WWW服務,總要有網絡,是以/etc/init.d/network就

必須先要被啟動啦,現在應該有點了解S或者K後面數字的意思了吧,那就是執行的順序,看看哪個是最後一個被執行的項目呢,其實是S99local,也就是/etc/rc.d/rc.local檔案

用于自定義開機啟動程式/etc/rc.d/rc.local

例如在完成預設runlevel指定的各項服務的啟動後,還有一些其他的動作想要完成,例如給某人寄一份信,通知他,啟動完畢,那就不需要再制作一個

shell script 放置在/etc/init.d/裡面,通過連接配接方式連結到/etc/rc5.d/裡面,可以将執行的指令放在/etc/rc.d/rc.local檔案中,是以可以把自己制作的并且需要

在開機時啟動的腳本完整檔名寫入/etc/rc.d/rc.local,如此一來,開機就會将我的shell script 執行過

加載終端機或X-Window接口

在完成了所有服務的啟動後,接下來Linux就會啟動終端機或者X window來等待使用者登入

run level 2,3,4,5時,都會執行/sbin/mingetty這個咚咚,而且執行六個,也就是Linux會提供六個純文字終端機,因為mingetty就是啟動終端機的指令

要注意的是那個 respawn 的 init 動作項目,他代表當後面的指令被終止時,init會主動重新啟動該項目,也就是登入tty1終端機接口後,以exit離開後

系統還會重新顯示等待使用者輸入的畫面,如果改天不想要六個終端機,可以取消某些終端機接口,将不需要的終端的那行資訊給批注掉,下次重新啟動

後,你的Linux就不會顯示那幾個終端了,除了終端機之外,init還會執行/etc/X11/prefdm-nodaemon那個指令,他主要就是啟動X window

開機中遇到的主要配置檔案 /etc/rc.d/rc.sysinit以及/etc/rc.d/rc等等, 這些腳本都會使用相當多的系統配置檔案,那麼系統開機會用到的配置檔案大多放置

/etc/sysconfig目錄下,同時,由于核心還是要加載一些驅動程式(核心子產品),此時系統自定義的裝置與子產品對應檔案/etc/modprobe.conf就很重要了

/etc/modprobe.conf檔案

前面rc.sysinit檔案中談到加載使用者自定義子產品,就是在/etc/sysconfig/modules目錄下,某些條件下我們需要對子產品的一些參數進行規劃,此時

我們就要使用到/etc/modprobe.conf檔案

/etc/sysconfig/*下所有的幾個重要檔案

authconfig 這個檔案主要規範使用者的身份認證的機制,包括使用本機的/etc/passwd /etc/shadow以及/etc/shadow密碼記錄使用何種加密算法

還有是否使用外部密碼伺服器提供的帳号驗證(NIS LDAP)等,系統預設使用MD5加密算法,不使用外部的身份驗證機制

clock 此檔案設定Linux主機的時區,可以使用格林威治時間(GMT),也可以使用本地時間(local) 在clock檔案内的設定項目【ZONE】所參考的

時區位于/usr/share/zoneinfo目錄下的相對路徑中,而且要修改時區的話,還得将/usr/share/zoneinfo/Asia/Shanghai這個檔案複制成為

/etc/localtime才行.

i18n 設定語系的使用方面,更改這個i18n的檔案,可以設定目前的語系環境

keyboard & mouse

keyboard與mouse就是設定鍵盤與滑鼠的形式

network 可以設定是否需要啟動網絡,以及設定主機名還有網關(GATEWAY)這兩個重要資訊

network-scripts/ 主要用來設定網絡卡

Run level 的切換 其實run level的不同僅是/etc/rc[0-6].d裡面啟動的服務不同而已,不過,依據開機是否自動進入不同run level 的設定

1 每次開機執行預設的run level 亦即是 id:5:initdefault裡頭的數字

2 如果隻是暫時的變更系統的run level時,則使用init[0-6]來進行run level的變更,但下次重新啟動,依舊會以/etc/initta的設定為準

如果想從 init 5 切換為init 3 不同的run level 隻是加載的服務不同,亦即是/etc/rc5.d/還有/etc/rc3.d内的Sxx與Kxx有差異而已

是以切換的時候先比對/etc/rc.d/及/etc/rc5.d内的K與S開頭的檔案

在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 K 開頭檔案,則予以關閉;

在新的 runlevel 亦即是 /etc/rc3.d/ 内有多的 S 開頭檔案,則予以啟動;

檢視目前的run level ,可以在bash當中輸入runlevel即可,結果顯示5 3  看吧!前一個是 runlevel 5 ,目前的是 runlevel 3 啦

核心與核心子產品

整個開機的過程中,能否成功的驅動我們主機的硬體配備,是核心的工作,而核心一般是壓縮檔案,是以使用核心之前,就要将他解壓縮

才能加載主存儲器中。目前為了應付日新月異的硬體,目前的核心都是具有【可讀取子產品化驅動程式】的功能,亦即所謂的子產品化功能,所謂

的子產品化可以想象成是一個插件,該插件由硬體開發商提供,也有可能我們的核心本來就支援,不過,較新的硬體,通常都需要開發商提供驅動

程式子產品啦

核心與核心子產品放置的位置

核心: /boot/vmlinuz 戒 /boot/vmlinuz-version;

核心解壓縮所需 RAM Disk: /boot/initrd (/boot/initrd-version);

核心子產品: /lib/modules/version/kernel 戒 /lib/modules/$(uname -r)/kernel;

核心原始碼: /usr/src/linux (要安裝才會有!否則預設不安裝的!)

如果核心被順利的加載系統當中了,那麼會有幾個資訊記錄下來

核心版本 : /proc/version

系統核心功能 : /proc/sys/kernel

那麼如果有個新的硬體,偏偏我的作業系統不支援,辦法有倆個:

1 重新編譯核心 并加入最新的硬體驅動程式原始碼

2 将該硬體的驅動程式編譯成為子產品 在開機時加載該子產品  牽涉到 原始碼與 tarball

核心子產品與相依性

既然要處理核心子產品,自然就要了解我們核心提供的子產品之間的相關性,核心子產品放置在/lib/modules/$(uname -r)/kernel 當中

裡面主要有幾個目錄

arch :與硬體平台有關的項目,例如 CPU 的等級等等;

crypto :核心所支援的加密的技術,例如 md5或者是 des 等等;

drivers :一些硬體的驅動程式,例如顯示擴充卡、網絡卡、PCI 相關硬體等等;

fs :核心所支援的 filesystems ,例如 vfat, reiserfs, nfs 等等;

lib :一些函數庫;

net :與網絡有關的各項協定資料,還有防火牆子產品 (net/ipv4/netfilter/*)等等;

sound :與音效有關的各項子產品;

可以通過檢查/lib/modules/$(uname -r)/modules.dep 這個檔案 ,他會記錄了核心支援的子產品的各項相依性

那麼這個檔案是如何建立的,很簡單,是利用depmod這個指令就可以達到建立該檔案的需求了

 不加任何參數時,depmod會主動的去分析目前核心的子產品,并且重新寫入/lib/modules/$(uname -r)/modules.dep當中

-A 則depmod會去搜尋比modules.dep内還要新的子產品,如果真找到新子產品,才會更新

-n 不寫入modules.dep 而是将結果輸出到螢幕上(standard out)

-e 顯示出目前已加載的不可執行的子產品名稱

若制作好一個網卡驅動程式,檔名為a.ko 該如何更新核心相依性

cp -a.ko /lib/modules/$(uname -r)/kernel/drivers/net

接着執行depmod ,該程式會到/lib/modules/$(uname -r)/kernel , 并且依據相關目錄的定義将全部的子產品捉出來分析,最終将分析的結果寫入

modules.dep檔案中,這個檔案很重要,因為他會影響到modprobe指令的應用

核心子產品的觀察

lsmod,使用lsmod之後,系統會顯示出目前已經存在于核心當中的子產品,目前的内容包括

子產品名稱(Module);

子產品的大小(size);

此子產品是否被其他子產品所使用 (Used by)。

mii 9409 2 8139too,8139cp <==mii 還被 8139cp, 8139too 使用

mii這個子產品會被8139too所使用 , 簡單的說 【當你要加載 8139too 時,需要先加載 mii 這個子產品才可以順利的加載 8139too】

除了顯示出目前的子產品外,還可以查閱每個子產品的資訊 ,那如果想要知道mii是什麼,可以用modinfo來觀察的

modinfo

-a :僅列出作者名稱;

-d :僅列出該 modules 的說明 (description);

-l :僅列出授權 (license);

-n :僅列出該子產品的詳細路徑

核心子產品的加載和移除

如果想要自行手動加載子產品,是使用modprobe這個指令來加載子產品,因為modprobe會主動的去搜尋modules.dep的内容,先客服了子產品

的相依性後,才決定需要加載的子產品有那些,至于insmod則完全由使用者自行加載一個完整檔案名的子產品,并不會主動分析子產品相依性

insmod /lib/modules/$(uname -r)/kernel/fs/cifs/cifs.ko 嘗試載入cifs.ko這個檔案系統子產品

lsmod | grep cifs 檢視

rmmod cifs 将剛剛加載的cifs子產品移除

-f :強制将該子產品移除掉,不論是否正被使用;

-w :若該子產品正被使用,則 rmmod 會等待該子產品被使用完畢後,才移除他!

不過使用insmod和rmmod的問題就是, 你必須要自行找到子產品的完整檔案名才行,而且萬一子產品的相依屬性有問題時,你将無法直接加載

或移除該子產品,是以還是建議直接使用modprobe來處理子產品加載的問題,這個指令的用法是:

-c :列出目前系統所有的子產品!(更詳細的代号對應表)

-l :列出目前在 /lib/modules/`uname -r`/kernel 當中的所有子產品完整檔案名;

-f :強制加載該子產品;

-r :類似 rmmod ,就是移除某個子產品

modprobe cifs 因為該完整檔案名已經記錄到/lib/modules/$(uname -r)/modules.dep當中的緣故

移除的話執行modprobe -r cifs

是以使用modprobe要比insmod和rmmod友善的多,因為他是主要去搜尋modules.dep的記錄,是以,當然可以克服子產品的相依性問題

是以還不需要知道該子產品的詳細路徑

modprobe vfat 接着執行 lsmod | grep vfat 檢視到:

vfat 15809 0

fat 51165 1 vfat <==原來就是 fat 這個子產品啊!

modprobe -r vfat <==測試完移除此子產品

核心子產品的額外參數設定: /etc/modprobe.conf

例如我的網絡卡eth0使用ne,但是eth1同樣使用ne 為了避免同一個子產品會導緻網絡卡錯亂,是以我們先找到eth0與eth1的I/O與IRQ

eth0 : I/O (0x300) 丏 IRQ=5

eth1 : I/O (0x320) 丏 IRQ=7

vi /etc/modprobe.conf

alias eth0 ne

alias eth1 ne

options eth0 io=0x300 irq=5

options eth1 io=0x320 irq=7

如此一來我們的linux就不會捉錯網絡卡的對應了

在經曆了開機流程後,會發現boot loader 是載入核心的重要工具,沒有boot loader的話 那麼kernel根本就沒有辦法被系統加載

是以現在來談一些boot loader的功能,Linux最主流的grub這個boot loader

boot loader 的兩個stage

boot loader具有選單功能,直接加載核心檔案以及控制移交的功能,系統必須要有loader才有辦法加載作業系統的核心 ,但是MBR

的整個硬碟的第一個分區中的一個區塊,整個大小為446bytes ,而loader功能這麼強,光是程式代碼與設定資料不可能隻占用不到

446bytes的容量,為了解決這個問題,是以Linux将boot loader的程式代碼執行與設定值加載分成兩個階段來執行

Stage 1:執行 boot loader 主程式:

第一階段為執行 boot loader 的主程式,這個主程式必須要被安裝在開機區,亦即是MBR或者是boot sector,但是因為MBR實在太小,是以

MBR或boot sector通常僅安裝boot loader的最小主程式,并沒有安裝loader的相關配置檔案

Stage 2:主程式加載配置檔案:

第二階段透過boot loader加載所有配置檔案和相關的環境參數檔案(包括檔案系統定義與主要配置檔案menu.lst)一般來說 配置檔案都在/boot 底下

這些grub有關的檔案都放置在/boot/grub中,其實在這個目錄下最重要的就是

配置檔案menu.lst以及各個檔案系統的定義,我們loader讀取了

檔案系統定義資料後,就能夠認識系統并讀取在該檔案系統内的核心檔案,至于grub的配置檔案檔名,其實是menu.lst的,隻是Red Hat裡面

被定義為/boot/grub.conf,不過建議還是記憶menu.lst比較好

grub的配置檔案/boot/grub/menu.lst與選單類型,

由于grub認識的檔案系統真的非常多,是以grub才會被那麼廣泛使用,grub的優點包括:

1 認識與支援較多的檔案系統,并且可以使用grub的主程式直接在檔案系統中搜尋核心檔案

2 開機的時候,可以自行編輯與修改開機設定項目 類似bash的指令模式

3 可以動他搜尋配置檔案,而不需要在修改配置檔案後重新安裝grub,亦即我們隻要修改完menu.lst 裡頭的設定後,下次開機就

生效了

menu.lst檔案的内容

安裝MBR的grub主程式,最重要的任務就是從磁盤中加載核心檔案,以讓核心能夠順利的驅動整個系統的硬體,是以grub必須認識

硬碟才行,那麼grub如何認識硬碟呢? grub對硬碟的代号設定與傳統的Linux磁盤代号可以完全的不同的,grub對硬碟的識别使用

的是如下内容

(hd0,0) 跟 /dev/hda1看上去不相幹,其實是同一個東西

(hd0,0) 硬碟代号以小括号包起來,硬碟以hd表示,後面接一組數字,以【搜尋順序】作為磁盤的編号,第一個搜尋到的硬碟為0

第二個為1号,依次類推,每顆硬碟的第一個partition代号為0 ,依次類推

是以(hd0,0)表示第一顆硬碟的第一号分割槽,反正grub裡面開始的數字是0而不是1

 vim /boot/grub/menu.lst

default=0  <== 預設開機選項,使用第 1 個開機選單 (title)  有幾個title, 那麼這個default最大為title - 1

timeout=5  <== 若5秒内未動鍵盤,使用預設選單開機  等待5秒,也可以設定為0代表直接使用default值進行開機而不讀秒,timeout則直接進入選單,不讀秒

splashimage=(hd0,0)/grub/splash.xpm.gz <==背景圖示所在的檔案 開機時候的背景色彩,由于這裡将/boot這個目錄獨立成為/dev/hda1,是以hd(0,0)也是同樣的含義

在/dev/hda1裡面的grub/splash.xpm.gz的意思

hiddenmenu  <==讀秒期間是否顯示出完整的選單畫面(預設隐藏) ,開機的時候是否顯示選單,預設不顯示選單,想要顯示的話,就将這行批注掉

title CentOS (2.6.18-92.el5) <==第一個選單的内容

root (hd0,0)

kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet

initrd /initrd-2.6.18-92.el5.img

title以前的四行,都是屬于grub的整體設定,包括預設的等待時間與預設的開機項目,還有顯示的畫面特性,至于title後面才是

指定開機的核心檔案或者 boot loader控制權轉移到下個loader(此過程稱為chain-loader),每個title後面接的是【該開機項目名稱的顯示】

亦即是在選單出現時,選單上面的名稱而已

1 直接指定核心開機

既然要指定核心開機,是以當然要找到核心檔案,此外,還要用到initrd的RAM Disk的配置檔案,當尚未開機完成,是以我們必須要以grub的

磁盤識别方式找出完整的kernel與initrd檔名才行.

先指定核心檔案放置的partition,再讀取檔案(目錄樹), 最後才加入檔案的實際檔案名與路徑(kernel與initrd)

由于此處 /boot 為 /dev/hda1 是以核心檔案的設定則成為:

root(hd0,0)  <==代表核心檔案放在那個 partition 當中而不是根目錄,此處根目錄位/dev/hda2

kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet  由于開機過程中需要挂載根目錄,是以kernel後面接的那個root=LABEL=/1值得就是

Linux根目錄在那個partition的意思,這裡使用LABEL轉标來挂載根目錄至于 rhgb 為色彩顯示而 quiet 則是安靜模式

initrd :就是前面提到的 initrd 制作出 RAM Disk 的檔案檔名啦!

也可以按以下直接指定partition與檔名,不需要額外指定核心檔案所在的裝置代号

接着想想/boot有獨立分割與無獨立分割的情況

無獨立分割,系統分割是/dev/hda1 (/), /dev/hda2 (swap)  核心檔案為/boot/vmlinuz  那麼menu.lst内容如何編寫核心檔案位置

kernel (hd0,0)/boot/vmlinuz root=/dev/hda1

獨立分割  /dev/sda1 (/boot), /dev/sda5 (/)   那麼menu.lst内容編寫核心檔案為

kernel (hd0,0)/vmlinuz root=/dev/hda5

2 利用chain loader 的方式轉交控制權

所謂chain loader 就是将控制權交給下一個boot loader而已,是以grub不需要認識和找出kernel的檔名,隻要将boot的控制權交給下一個boot

sector或MBR内的boot loader而已,通常也不需要去查驗下一個boot loader的檔案系統

一般來說chain loader的設定隻要有兩個就夠了,一個是預計要前往的boot sector所在的分割槽代号,另一個則是設定chainloader在那個分割槽

的boot sector(第一個扇區)上,假設windows的分割槽在 /dev/hda1,且我又隻有一顆硬碟,那麼要grub将控制權交給windows的loader.

vi /boot/grub/menu.lst

title Windows partition

root (hd0,0) <==設定使用此分割槽 (hd0,0)就是windows的C槽所在的磁盤,

chainloader +1 <== +1 可以想成第一個扇區,亦即是 boot sector 開機管理程式 不過windows的開機碟需要設定位活化狀态

是以grub預設會去檢驗該分割槽的檔案系統,可以将内容改寫成

rootnoverify (hd0,0)  <==不檢驗此分割槽

chainloader +1

makeactive  <==設定此分割槽為開機碟(active)

還可以将運作windows期間隐藏某個分割槽需要加上 hide (hd0,4) <==隐藏 (hd0,4) 這個Linux分割槽

initrd的重要性,在于提供開機過程中所需要的重要核心子產品,并且讓系統開機過程可以順利完成,子產品位于/lib/modules/$(uname -r)/kernel/ 當中

各個distribution提供的核心都會附上initrd檔案,但如果有特殊需要想要重置initrd檔案的話,可以使用mkinitrd

mkinitrd [-v] [--with=子產品名稱] initrd 檔案名 核心版本

-v :顯示 mkinitrd 的運作過程

--with=子產品名稱:子產品名稱指的是子產品的名字而已,不需要填寫檔名

例如ext3檔案系統子產品為底下的檔案名/lib/modules/$(uname -r)/kernel/fs/ext3/ext3.ko 那你應該寫成 --with = ext3就好了,省略.ko

initrd檔名:你所要建立的initrd檔名,盡量取有意義的名字

核心版本: 某一個核心的版本,如果是目前的核心則是【$(uname -r)】

以 mkinitrd 的預設功能建立一個 initrd 虛拟磁盤檔案

mkinitrd -v initrd_$(uname -r) $(uname -r)

增加 8139too 這個子產品的 initrd 檔案

mkinitrd -v --with=8139too initrd_vbirdtest $(uname -r)

測試和安裝grub

Linux主機本來就是使用grub作為loader的話,那麼不需要安裝grub,因為grub本來就會去主動讀取配置檔案,如果本來并非使用的是

grub的話,那麼就需要來安裝了,使用grub-install将一些必要的檔案複制到/boot/grub裡面去,

因為boot loader有兩個stage,這個grub-install就是安裝配置檔案,包括檔案系統定義檔與menu.lst等等,如果想要将grub的stage1

主程式安裝起來,就需要使用grub shell 的功能

grub-install [--root-directory=DIR] INSTALL_DEVICE

将 grub 安裝在目前系統的 MBR 底下,我的系統為 /dev/hda:

我的 /home 為獨立的 /dev/hda3 ,如何安裝 grub 到 /dev/hda3

grub-install --root-directory=/home /dev/hda3

這樣home目錄下就會多出了/boot/grub/的目錄

是以說grub-install是安裝grub相關的檔案到你的裝置上面去等待在開機時被讀取,但還需要設定menu.lst。再以grub shell 來安裝

grub主程式到MBR或者是boot sector上面去

vim /boot/grub/menu.lst 設定三個開機選單

1. 假設 /dev/hda1 内含有 boot loader ,此 loader 如何取得控制權?

2. 如何重新讀取 MBR 内的 loader ?

3. 利用你原本的系統核心檔案,建立一個可強制迚入單人維護模弅的選單

1./dev/hda1 boot sector <==本例中的第一個新增選單      root (hd0,0)      chainloader +1

2 title MBR loader   root (hd0)     <==新增的第二個選單   在<==MBR 為整顆磁盤的第一個扂區,是以用整顆磁盤的

3  title single user mode   <==新增的第三個選單(其實由原本的 title 複制來的)

配置檔案處理完畢,如果想要知道/dev/hda1底下到底有沒有包含grub的主程式

是以我們想要将 grub 主程式再次的安裝到 /dev/hda1 的 boot sector, ,也想要重新安裝grub 到 MBR 上面去

此時我們就得要使用grub shell

用『 root (hdx,x) 』選擇含有 grub 目錄的那個 partition 代号;

用『 find /boot/grub/stage1 』看看能否找到安裝資訊檔案;

用『 find /boot/vmlinuz 』看看能否找到 kernel file (不一定要成功!); 

用『 setup (hdx,x) 』或『 setup (hdx) 』将 grub 安裝在 boot sector 或 MBR;

用『 quit 』來離開 grub shell !

我們需要安裝的就是那個stage1,那才是grub的主程式,而且配置檔案通常與主程式擺在同一個目錄下,是以我們需要使用

root(hd0,0)去找到/boot/grub/stage1,接下來,調用grub來進入grub shell 進入時會出現一個grub 的提示字元

grub

1 先設定一下含有grub目錄的那個partition

root(hd0,0)

2 搜尋一下,是否存在stage1這個資訊檔案

grub> find /boot/grub/stage1

(hd0,2)

看到怎麼隻有一個,明明有/boot/grub與/home/boot/grub , 因為/boot是獨立的,是以要找到該檔案就得要用如下的方式

grub> find /grub/stage1

(hd0,0) 這樣就能夠找到了 找到的是裝置内的檔案,不是目錄樹

3 搜尋一下是否可以找到核心  /boot/vmlinuz-2.6.18-92.el5

find /vmlinuz-2.6.18-92.el5

(hd0,0) 因為/boot/是獨立的,是以不需要寫成 /boot/vmlinuz-2.6.18-92.el5

将主程式安裝上去吧!安裝到 MBR 看看!

執行setup(hd0)

那麼再重複安裝到我的/dev/hda1 亦即是boot sector當中

 setup (hd0,0)

設定好後,接着執行quit退出grub指令

如此以來,已經将grub安裝到MBR及bootsector裡面去了,而且讀取的是(hd0,0)裡面的/grub/menu.lst那個檔案

最後總結一下:

1. 如果是從其他 boot loader 轉成 grub 時,得先使用 grub-install 安裝 grub 配置檔案;

2. 開始編輯 menu.lst 這個重要的配置檔案;

3. 透過 grub 來将主程式安裝到系統中,如 MBR 的 (hd0) 戒 boot sector 的 (hd0,0) 等等。

都做好後重新啟動來查閱看看

由于将隐藏功能去掉了,你會直接看到這四個選單,如果按下控制權轉交

e 進入grub shell的編輯畫面

o 在遊标所在行底下再新增一行

d 将遊标所在行删除

按下【enter】,然後輸入b來boot,就可以開機了,而當/boot/grub/menu.lst設定錯誤時,導緻無法順利開機的話,可以使用

grub的選單部分,使用grub shell的方式去查詢(find)或者是直接指定核心檔案,就能夠開機了

那如果grub可能發生錯誤,導緻grub都無法啟動,那麼根本就無法使用grub的線上編輯功能,此時可以利用具有grub開機的CD

來開機,然後再以CD的grub的線上編修,同樣可以使用硬碟上面的核心檔案來開機啦

關于核心功能當中的vga設定

tty1-tty6除了80*24的分辨率外,還能夠有其他分辨率的支援,前提核心必須要支援FRAMEBUFFER_CONSOLE 這個核心功能選項扄行

如何确定是否支援,可以查閱/boot/config-2.6.18-92.el5 這個檔案,然後這樣搜尋

grep 'FRAMEBUFFER_CONSOLE' /boot/config-2.6.18-92.el5

CONFIG_FRAMEBUFFER_CONSOLE=y 結果y表示支援,而n表示不支援

那麼如何調整 tty1 ~ tty6 終端機的分辨率呢 此為十進制數值

假設你想要将你的終端機螢幕分辨率調整到 1024x768 ,且顔色深度為 15bit 色的時候,就得要指定

vga=790 那個數字! 丼例來說,tty1 就想要這樣的分辨率時,你可以這樣做:

kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790 重新啟動後,去到tty1,就已經是 1024x768 的分辨率

BIOS 無法讀取大硬碟的問題 最好是重新安裝,将制作出/boot這個partition,是以以後安裝時,最好将/boot這個分割槽分割出來

為個别選單加上密碼

首先,必須要建立密碼,而且還是要加密過後的,不然别人跑到/boot/grub/menu.lst裡面就能探查到你的開機密碼了,我們可以

透過grub提供的md5編碼處理

grub-md5-crypt

$1$kvlI0/$byrbNgkt/.REKPQdfg287. <==由$開始到.結束這就是産生的 md5 密碼!将這個密碼複制下來,假如我們要将第一個選項

加入這個密碼,而第四個選項加入另外的密碼

title CentOS (2.6.18-92.el5)

password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287.

root (hd0,0)

kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790

initrd /initrd-2.6.18-92.el5.img

title single user mode

password --md5 $1$GFnI0/$UuiZc/7snugLtVN4J/WyM/

root (hd0,0)

kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet single

initrd /initrd-2.6.18-92.el5.img

我們兩個選單進入的密碼并不相同,可以進行人員的分類,此時就一定要輸入密碼才能進入開機流程,如果你在遠端使用

reboot重新啟動,并且主機前面并沒有任何人的話,你的主機并不會主動進入開機程式

你必須要注意的是passwd這個項目一定要在title底下的這一行,不過,此項功能還是可能被破解,使用者按e進入編輯模式

接着删除密碼字段,接着重新啟動開機流程,是以隻好通過整體的password放在所有的title之前,然後在title底下的第一行

設定lock 那使用者想要編輯時,也需要輸入密碼的

vim /boot/grub/menu.lst

default=0

timeout=30

password --md5 $1$kvlI0/$byrbNgkt/.REKPQdfg287. <==放在整體設定處

splashimage=(hd0,0)/grub/splash.xpm.gz

#hiddenmenu

title CentOS (2.6.18-92.el5)

lock <==多了死鎖的功能

root (hd0,0)

kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/1 rhgb quiet vga=790

initrd /initrd-2.6.18-92.el5.img

重新啟動後,下方出現p的功能,由于2,3,4選單沒有使用lock 是以這三個選單使用者還是可以執行開機程式,而第一個

選單由于有lock項目,除非輸入密碼,否則第一個選單是無法被載入執行的,是具有保密menu.lst的功能

開機過程的問題解決

由于很多時候某些設定的錯誤,導緻Linux開機無法順利的開機成功,此時可以進入run level1單使用者模式進行處理

例如忘記 root 密碼的解決之道

single 參數 進入單人使用者模式下,執行passwd這個指令來重建root的密碼

init 配置檔案錯誤

前一個root密碼挽救的方法其實可以用在很多地方,唯一一個無法挽救的情況,那就是/etc/inittab這個檔案設定錯誤導緻無法

開機,根據開機流程,我們知道runlevel0-6 都會讀取/etc/inittab配置檔案,是以你使用single model(runlevel 1) 當然也是要

讀取/etc/inittab來進行開機的,那既然無法進入單人維護模式,既然預設的init無法執行,那我們就告訴核心不要執行init 改

為呼叫bash ,可以略過init 同樣在grub edit 的情況下這樣寫

grub edit> kernel /vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet init=/bin/bash

我們指定了核心呼叫的第一支程式(init)變成/bin/bash,是以/sbin/init就不會被執行,又根據開機流程的說明,我們知道此時可以

利用root取得bash來工作,此時除了根目錄外,其他的目錄都沒有被加載,根目錄被加載成為隻讀狀态,是以我們需要手動的

将根目錄重新挂載成可擦寫, mount -o remount,rw / 至于mount -a 則是參考fstab的内容重新挂載檔案系統,此時你又可以

進行救援的工作了,隻是救援完畢後,你得要使用reboot重新啟動一次才行

BIOS 磁盤對應的問題 (device.map)

如果有兩個硬碟分别安裝windows和linux的作業系統,接着調整BIOS的開機裝置順序,此時每顆磁盤的MBR個别有不同作業系統的

loader,問題是 grub對磁盤的裝置代号使用的是偵測到的順序,就是說,你調整BIOS磁盤開機順序後,你的menu.lst内的裝置代号

就可能會對應到錯誤的磁盤上了,沒關系我們可以透過/boot/grub/device.map這個檔案來寫死每個裝置對grub磁盤代号的對應

舉例

cat /boot/grub/device.map

(fd0) /dev/fd0

(hd0) /dev/hda

也可以利用grub-install 的功能

grub-install --recheck /dev/hda1 這樣device.map 會主動的被更新了

因檔案系統錯誤而無法開機

最容易出錯的設定通常就是/etc/fstab這個檔案了,最容易寫錯參數,又沒有經過mount -a來測試挂載,就立刻直接重新啟動

看到 for type Control-D to continue); 輸入root的密碼來取得bash并以mount -o remount, rw /将根目錄挂載可以擦寫後,繼續處理

造成上述畫面可能的原因還有 不正常關機,如果是磁盤錯亂的話 fsck告知那個出錯,此時利用fsck 去檢測那個裝置,等到系統發現錯誤

并且出現clear【Y/N】輸入Y吧,如果此時依然無法進入Linux,此時将系統中重要的資料複制出來,然後重新安裝,并且檢驗一下

是否磁盤有損傷的現象,一般執行fsck就能夠順利再次進入Linux了

利用chroot切換到另一顆磁盤工作

可以暫時将根目錄移動到某個目錄下,然後去處理某個問題,最後再離開該root而回到換本的系統當中

例如同一個主機上面安裝了兩個linux系統,假設我的第一個Linux無法進入了,那麼我可以使用第二個Linux開機,然後在第二個Linux系統

下将第一個Linux挂載起來,最後用chroot變換到第一個Linux,就能夠進入第一個Linux的環境當中去處理工作了

同樣也可以将你的Linux硬碟拔到另一個Linux主機上面去,然後用這個chroot來切換,以處理你的硬碟問題

用盡任何方法,進入一個完整的Linux系統(run level 3或5)

假設有問題的Linux磁盤在/dev/hdb1上面,且整個系統的排列是

挂載點    裝置檔案名

/          → /dev/hdb1

/var → /dev/hdb2

/home → /dev/hdb3

/usr → /dev/hdb5

那麼在我目前的這個linux底下 我可以建立一個目錄,然後這樣做:

挂載點      裝置檔案名

/chroot/    → /dev/hdb1

/chroot/var/     → /dev/hdb2

/chroot/home/     → /dev/hdb3

/chroot/usr/     → /dev/hdb5

全部挂載完畢後,再輸入 chroot /chroot 你就會發現 根目錄(/) 變成那個/dev/hdb1的環境

繼續閱讀