2007年10月19日 星期五

Linux 系統裁減指南(LiPS) (繁體中文版) --(二)

Linux 系統裁減指南(LiPS) (繁體中文版) --(一)
http://www.ceasar.tw/modules/news/article.php?storyid=191

Linux 系統裁減指南(LiPS) (繁體中文版) --(二)
http://www.ceasar.tw/modules/news/article.php?storyid=192


5 根文件系統

  創建根文件系統比編譯內核要複雜的多,也更難理解。這裡的關鍵是掌握init
rd(初始化RAM盤)的使用方法。
5.1 根文件系統
  這裡我們將要創建的根文件系統與通常Linux主機的根文件系統類似,只是它應
該僅僅包括系統運行所必須的應用程序、庫和相關文件的最小集合。根文件系統的
尺寸大小是一個重要的指標。
5.2 文件系統的內容
5.2.1 應用程序(applications)
  /bin,/sbin,/usr/bin,/usr/sbin
  應用程序大致可以分為3部分,第一是操作系統正常運行所需的基本工具軟件,
比如bash,cp,rm等;第二是提供某項服務的服務器軟件,比如httpd,telnetd,
proftpd等;第三是我們所開發的應用程序。其實後面講的配置文件等也可以粗略按
照這個原則來分類。
  到底需要複製哪些軟件,彈性是比較大的,很多軟件都是可要可不要,可以實
際情況靈活選擇。這個列表可能很長,並且變化也比較大,因此不在這裡列出。
  為了進一步減小所創建的根文件系統的尺寸,可以考慮使用下列工具包軟件來
替代某些標準的工具:
O BusyBox(http://www.busybox.net)
O TinyLogin(http://tinylogin.busybox.net)
O Embutils(http://www.fefe.de/embutils/)
  其詳細使用方法請參考相關資料,此處不再贅述。LIPS的實現目前沒有使用這
些軟件包。
5.2.2 設備文件(device files)
  /dev
  設備文件也可以稱作設備節點(device node)。設備文件非常重要,缺少某些
有些設備文件可能導致系統不能正常運行甚至不能引導。有些設備文件是必須的,
而更多的是根據具體目標系統的硬件配置來進行取捨。
  比如硬盤的設備文件,在完整的系統中一般有hda,hdb,……,hdt,即最多支
持20個IDE硬盤,每個硬盤有hdX1,hdX2,……,hdX32,(其中X表示a-t),即支
持32個分區,另外還有表示SCSI硬盤的節點。根據實際情況,如果只需要支持少量
的硬盤、少量的分區,這些節點可以被大大簡化。如果目標系統中沒有的設備,其
對應的設備文件也可以省掉。
設備文件
描述
/dev/console
系統控制台設備,非常重要。
/dev/fd0
第一個軟驅
/dev/hda
/dev/hda[1-8]
IDE硬盤及分區
/dev/initctl
實際上是一個FIFO設備,跟init有關(切換運行級別時用於新init與原init通信)

/dev/initrd
Initial RAM disk
/dev/input
(目錄)Input core(包括遊戲桿、鼠標等)
/dev/kmem
內核虛擬內存
/dev/loop[0-7]
Loopback設備
/dev/mem
訪問物理內存
/dev/null
NULL設備
/dev/psaux
PS/2鼠標
/dev/ptmx
UNIX98 PTY master
/dev/pts
(目錄)UNIX98 PTY slaves
/dev/ptyp[0-7]
偽終端主設備(遠程登錄使用)
/dev/ram[0-7]
/dev/ramdisk
/dev/ram
RAM Disk設備。至少/dev/ram0是應用initrd機制所必須的。
/dev/ramdisk鏈接到/dev/ram0,是為了兼容老版本內核而保留的。
/dev/ram鏈接到/dev/ram1。
/dev/random
隨機數發生器
/dev/sda
/dev/sda[1-8]
SCSI磁盤及分區設備
/dev/shm
共享內存設備
/dev/systty
指向系統tty設備的符號鏈接,一般是tty0。
/dev/tty
當前TTY設備
/dev/tty[0-7]
虛控制台(Virtual console)
/dev/ttyp[0-7]
偽終端從設備
/dev/ttyS0
/dev/ttyS1
串口(COM1和COM2)
/dev/urandom
速度更快、安全性較差的隨機數發生器
/dev/zero
零設備,只能讀0出來
  設備節點的主設備號(Major)、次設備號(Minor)的文檔是內核源代碼中的
/Documentation/device.txt,如果有疑問可以查看這個文件[8]。
5.2.3 腳本和配置文件(scripts and configuration files)
  /etc
  /etc/rc.d目錄下的啟動腳本是系統的重要部分。必須對啟動腳本做相應的修改
以簡化系統的啟動過程。
  系統和各種應用程序用到的幾乎所有的配置文件都位於/etc目錄,是裁減Linu
x最麻煩的部分,最容易出問題。配置文件的選擇需要綜合很多方面的信息,需要對
系統有比較全面、深入的瞭解,並結合經驗才能做出正確的判斷。
配置文件
描述
/etc/default
(目錄)某個命令(比如useradd)的缺省設置(man useradd(8))
/etc/ld.so.cache
由ldconfig命令根據/etc/ld.so.conf文件產生
/etc/ld.so.conf
庫文件路徑配置文件,ldconfig命令根據該配置文件生成/etc/ld.so.cache
/etc/localtime
本地時間、時區設置
/etc/login.defs
全局缺省設置
/etc/fstab
文件系統列表(man fstab(5))
/etc/group
組文件(man group(5))
/etc/hosts
列出主機名和IP地址(man hosts(5))
/etc/init.d
符號鏈接到/etc/rc.d/init.d
/etc/initlog.conf
Initlog日誌配置文件(man initlog(8))
/etc/inittab
Init配置文件(man inittab(5))
/etc/ioctl.save
該文件包含了用於單用戶模式的串口和終端參數,因為這些參數是由getty設置的,
而在單用戶模式時沒有運行getty,所以用該文件保存參數。單用戶模式對系統安全
是個威脅,我們應該禁止使用單用戶模式,因此這個文件實際上並沒有必要複製過
來。
/etc/issue
登錄信息和標識文件(man issue(5))
/etc/modules.conf
模塊的配置文件(man modules.conf(5))
/etc/mtab
已經掛載的文件系統列表(man mount(8))
/etc/nsswitch.conf
Name Service Switch的配置文件(配置名稱服務數據源和查詢的順序)(man nss
witch.conf(5))
/etc/pam.d
放置PAM配置文件的目錄(有關PAM請參考5.5節)
/etc/passwd
用戶口令文件(man passwd(5))
/etc/profile
系統環境變量和登錄配置文件
/etc/rc.d
放置啟動腳本的目錄
/etc/services
列出可用的網絡服務及其端口(man services(5))
/etc/termcap
終端(terminal)功能數據庫(man termcap(5))
  還有那些跟特定應用程序相關的配置文件,比如apache服務器需要的/etc/htt
pd/conf/httpd.conf 等,此處不再一一列出。
5.2.4 庫文件(libraries)
  /lib,/usr/lib,/usr/share
  庫文件也是系統運行所必需的。到底需要哪些庫文件,是根據所複製的可執行
程序用 ldd 工具來確定的。比如,要知道/bin/bash需要哪些庫文件,使用如下命
令:
[root@lips xmdong]# ldd /bin/bash
libtermcap.so.2 => /lib/libtermcap.so.2 (0x40020000)
libdl.so.2 => /lib/libdl.so.2 (0x40024000)
libc.so.6 => /lib/tls/libc.so.6 (0x42000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
  對複製到新的根文件系統的每個可執行程序,都要使用這種方法來確定其所需
要的庫,然後把這些庫文件也複製過來。
  需要注意的是,有些庫文件使用上述方法是找不出來的,但是卻是系統必須的
。比如:
庫文件
描述
/lib/libnss_files*
這個庫是跟/etc/nsswitch.conf有關的,必不可少,否則系統不能正常使用。(ma
n nsswitch.conf(5))
/lib/security/pam_unix.so
這個庫跟PAM有關,是安全、認證方面的,必不可少,否則系統無法登錄。
  
  
5.2.5 必要的目錄
  /home,/mnt,/proc,/root,
  /var,/var/log,/var/run,/var/lock/subsys
  
  
5.3 初始化RAM盤(initrd)
  (參考資料[5])
  初始化RAM盤(initrd)提供了引導器加載RAM盤的能力。這個RAM盤可以被掛載
(mount)成根文件系統,並執行其上的程序。然後,可以從另一個設備掛載一個新
的根文件系統,而原來的根文件系統(也就是initrd)會被移到一個目錄裡並卸載

  initrd技術主要設計用來讓系統啟動過程可以分兩個階段進行,首先讓內核以
一組最小的、被編譯進內核裡的驅動程序來啟動,然後從initrd中加載其他的模塊

5.3.1 操作步驟
  使用initrd時,系統典型的引導步驟如下:
1) 引導器加載內核和初始化RAM盤;
2) 內核把initrd轉到一個一般的RAM盤中,並且釋放原來被initrd佔用的RAM;
3) initrd以可讀寫模式被掛載到根目錄;
4) 執行/linuxrc(linuxrc可以是任何可執行文件,包括shell腳本在內;它具有u
id 0即超級用戶的權限,基本上可以做init程序中能夠做的任何事情);
5) 在linuxrc中掛載真正的根文件系統;
6) linuxrc使用pivot_root系統調用,把真正使用的根文件系統掛載到根目錄;
7) 在根文件系統上執行通常的引導過程(比如執行/sbin/init);
8) initrd文件系統被刪除。
  注意,改變根目錄並不包括卸載舊的根文件系統,因此有可能在轉變過程中仍
有進程在initrd上運行。另外,掛載在initrd目錄下的根文件系統仍然是可用的。

5.3.2 引導選項
  initrd技術增加了下列引導選項:
initrd=
  裝入指定的文件作為初始化RAM盤。當使用 LILO 當引導器時,你可以用/etc/
lilo.conf 文件中 INITRD 這個配置參數,來指定初始化RAM盤文件。
noinitrd
  initrd的數據仍會保留,但不會裝入到一個RAM盤裡,真正使用的根文件系統將
會被掛載。initrd的數據能夠從 /dev/initrd 這個設備中被讀出來。注意,initr
d的數據可以是任何結構,並不一定必須是一個文件系統的映像,這個選項主要用來
進行debug。
  注意:/dev/initrd 是一個只讀並且只能使用一次的設備,最後一個程序一旦
關閉它, 所有數據將被釋放,而且設備也不能再被打開。
root=/dev/ram0
  initrd 先被掛載成根目錄,接著進行正常的啟動過程(這時RAM盤仍被掛載成
根)。
5.3.3 安裝
  首先:我們要在正常的根文件系統中創建一個容納initrd文件系統的目錄,例
如:
# mkdir /initrd
  對目錄名稱並沒有特別的限制,在pivot_root(2)的man手冊頁中有更詳細的說
明。
  如果根文件系統是在引導程序時被建立的(例如,你在製作安裝軟盤),在建
立根文件系統的同時應該創建 /initrd 目錄。
  在某些情況下initrd雖然未被掛載,只要有下列設備存在,它的內容仍是可被
訪問的。(注意:這個設備無法在 devfs 下使用)
# mknod /dev/initrd b 1 250
# chmod 400 /dev/initrd
  第二:支持初始化RAM盤的能力,及所有執行格式和文件系統模塊,都必須直接
編譯進內核,不能採用可加載模塊的方式。
  第三:必須製作一個RAM盤映像文件。大概的步驟是,在一個塊設備上創建一個
文件系統,把需要的文件複製進去,然後把這個塊設備的內容輸出成一個initrd文
件。目前至少有3種設備適合作為這種塊設備:
O 軟盤(能拿到任何地方試驗,但速度太慢);
O RAM盤(最快,但浪費內存);
O Loopback設備(比較合適的解決方案)。
  
  下面,我們將討論使用loopback設備創建initrd文件的方法。
  1)
  確認lookback設備已經配置到內核裡。
  2)
  創建一個適當大小的空白文件系統,例如:
# dd if=/dev/zero of=initrd bs=300k count=1
# mke2fs -F -m0 initrd
  3)
  把這個文件系統掛載進來,例如:
# mount -t ext2 -o loop initrd /mnt
  4)
  創建控制台設備。
# mkdir /mnt/dev
# mknod /mnt/dev/console c 5 1
  5)
  複製所有可能在initrd環境中用到的文件到/mnt目錄中。(別忘了/linuxrc文
件)
  6)
  initrd執行環境的測試需要反覆進行修正,為了避免不斷的重新啟動,可以使
用下列命令:
# chroot /mnt /linuxrc
  當然這樣啟用initrd還是有限制的,就是不能干擾正常系統的執行狀態(比如
重新配置網絡接口等等。如果在一個用pivot_root指令轉換根目錄的執行環境中,
就可以做這些事情了)。
  7)
  卸載這個文件系統:
# umount /mnt
  8)
  這時,初始化RAM盤系統就在「initrd」這個文件中了。可以把它壓縮小一點:

# gzip -9 initrd
  最後,必須啟動內核並載入initrd系統。需要設置下列引導參數:
root=/dev/ram0 init=/linuxrc rw
  (只有需要寫入initrd文件系統時才需要附加rw參數)。
  使用 LOADLIN 當引導器時,可以執行:
LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 i
nit=/linuxrc rw
  使用 LILO當引導器時,可以在 /etc/lilo.conf 中如下設置:
image = /boot/bzImage
initrd = /boot/initrd.gz
append = "root=/dev/ram0 init=/linuxrc rw"
  如果使用其他引導器,請參考相關文檔。
5.3.4 改變根目錄設備
  在執行完重要任務的尾聲,linuxrc一般會執行改變根目錄設備的動作,並讓所
有程序在真實的根文件系統中展開。這個過程包括下列步驟:
O 掛載新的根文件系統
O 把initrd自己轉到這個根文件系統中
O 結束所有舊的對initrd根文件系統的存取動作
O 卸載initrd文件系統並釋放RAM盤內存
  掛載新的根文件系統很簡單:只需要把它掛載到當前根文件系統中的一個目錄
下即可。例如:
# mkdir /new-root
# mount -o ro /dev/hda1 /new-root
  最終改變根文件系統由pivot_root()系統調用或者pivot_root工具來完成(參
考手冊頁pivot_root(8))。pivot_root可以把當前根文件系統轉移到新根的一個目
錄中,然後把指定的目錄當作新的根。在調用pivot_root之前,必須先為舊根準備
目錄,例如:
# cd /new-root
# mkdir initrd
# pivot_root . initrd
  現在,linuxrc仍然可以訪問舊的根文件系統。執行下列指令將完全結束與舊根
的聯繫:
# exec chroot . what-follows dev/console 2>&1
  其中what-follows是新根下面的一個程序,比如/sbin/init。(注意,這時如
果沒有/dev/console,系統不能啟動)。同時,為了保持不同版本之間的兼容性,
需要特別注意下列事項:
O 在調用pivot_root之前,當前目錄應該是新的根目錄;
O 使用「.」(當前目錄)作為pivot_root的第一個參數(新根),為舊根指定目錄
的第二個參數也要用相對路徑;
O chroot這個命令應該在新、舊根系統當中都能使用;
O 然後調用chroot轉移根文件系統;
O 在exec命令中使用象 dev/console 這樣的相對路徑。
  特別提示:讓initrd文件系統的目錄結構與新根文件系統的結構一致,有利於
轉換過程的順利。
  這時,initrd可以卸載,RAM盤也可以釋放:
# umount /initrd
# blockdev --flushbufs /dev/ram0
  注意:如果linuxrc或者它調用的其他程序的執行因為某種原因中斷,則會啟用
舊的change_root機制。
5.3.5 使用場合
  實現initrd的主要動機是允許系統安裝時模塊化的內核配置。這個過程大致如
下:
1) 系統可以用一個最小配置的內核從軟盤或者其他存儲媒體啟動,然後載入initr
d系統;
2) /linuxrc來決定需要什麼來進一步掛載真實的根文件系統(如設備類型、驅動程
序等)或者支持發行版媒體(如CD-ROM,網絡,磁帶等);
3) /linuxrc載入必須的內核模塊;
4) /linuxrc建立並安裝根文件系統;
5) /linuxrc調用pivot_root改變根文件系統,並通過chroot一個程序(繼續安裝過
程);
6) 安裝引導器;
7) 引導器被配置成裝入initrd以及相關的模塊,建立起系統環境;
8) 現在,系統可以引導,並執行其他的安裝任務。
  Initrd的關鍵作用是能夠多重配置一個正常操作的系統,而不需要用一個龐大
的內核,或者重新編譯、連接內核。在製作Linux發行版(光盤等)、系統恢復盤等
方面有廣泛的應用。
5.3.6 淘汰的根轉換機制(change_root)
  可以通過改寫/proc/sys/kernel/real-root-dev這個文件的數字值來改變真實
的根設備。例如:
# echo 0x301 >/proc/sys/kernel/real-root-dev
  但是這個機制已經被淘汰,雖然目前的內核仍然支持,不能保證以後的內核會
支持。所以不要使用。

5.4 系統初始化(init)
  (參考資料[10])
5.4.1 init的任務
  UNIX的init指的不是一個程序、而是一類程序。Init一般是指系統引導時執行
的第一個進程,也是唯一的進程。當內核完成計算機硬件的設置之後,就把控制權
交給init。內核只產生init這一個進程,而系統中其他所有進程都是由init負責產
生(spawn),主要包括各種系統服務進程,比如控制台的登錄會話(getty)。主
要任務包括:
O 產生其他進程;
O 重新啟動已經退出的進程;
O 負責清理系統中的「殭屍」進程(init是所有其他進程的祖先);
O 處理系統關機(stop所有進程,unmount文件系統);
  內核並不關心拿什麼來作為系統的init,可以是下列幾種選擇之一:
O SysVinit (作者:Miquel van Smoorenburg),或者
O simpleinit (作者:Peter Orbaek),或者
O 一個shell腳本,或者
O 嵌入式系統中你的應用程序。
  不過路徑名字必須是/sbin/init,/etc/init,或/bin/init(因為已經編譯到
內核裡面了)。如果這幾個路徑都找不到,系統就完蛋了。為了增加靈活性,內核
提供了命令行選項可以指定init路徑:「init=」。
5.4.2 SysVinit
/etc/inittab
/etc/rc.d
  大多數Linux發行版使用的init是SysVinit,也就是System V UNIX的實現。其
主要思想是規定了不同的「運行級別(runlevel)」。通過配置文件/etc/inittab
,定義了系統引導時做什麼,進入或者切換到一個運行級別時做什麼。配置文件每
一行的語法為:
id:runlevel:action:command
  細節請參考手冊頁inittab(5)。
  整個過程中用到的腳本都放在/etc/rc.d目錄。
5.4.3 兩種風格:Slackware vs. Debian
  關於配置文件/etc/inittab和腳本/etc/rc.d的實現和組織主要有兩種不同的風
格,其有代表性的發行版分別為Slackware和Debian(Redhat同Debian)。這兩種風
格之間有幾個明顯的區別,可以比較容易的識別。
  例如在/etc/inittab中,定義進入運行級別0時運行的腳本分別為/etc/rc.d/r
c.0和/etc/init.d/rc 0(在Redhat中/etc/init.d是指向/etc/rc.d/init.d的一個
符號鏈接,注意這裡0是腳本rc的命令行參數)。因此,Slackware風格的/etc/rc.
d中應該是一系列相對獨立的腳本,對應於配置文件中每個動作的定義(我沒有見過
Slackware哦)。
  在我們所熟悉的Redhat中,/etc/rc.d的組織要複雜的多,每個運行級別對應一
個子目錄/etc/rc.d/rcX.d(X表示運行級別0~6),下面放的是一系列形如SXXfoo
和KXXbar(S表示Start某個服務,K表示Kill某個服務,XX是兩位數字,決定了該腳
本執行的順序)的符號鏈接,指向/etc/rc.d/init.d中的腳本,每個腳本對應一項
服務程序。
  另外,還有兩個重要腳本值得一提:/etc/rc.d/rc.sysinit是系統引導時首先
要執行的(完成系統初始化的各項工作),而/etc/rc.d/rc.local在最後執行(類
似DOS的autoexec.bat)。
  讀一下/etc/rc.d/rc.sysinit,/etc/rc.d/rc和/etc/rc.d/init.d/中的某個腳
本,就會對Redhat的啟動過程和風格有比較清晰的瞭解。
  據說Slackware風格比Debian的速度要快一些。可能是後者的組織結構比較複雜
的緣故吧。

5.5 PAM
  (參考資料[11]?a href="Ahttp://www.kernel.org/pub/linux/libs/pam/,手冊頁pam" target="_blank">Ahttp://www.kernel.org/pub/linux/libs/pam/,手冊頁pam
(8))
5.5.1 什麼是PAM
  PAM(Pluggable Authentication Modules)是為瞭解決計算機系統中用戶認證
的問題而引入的一種實現方案。PAM的目標為:
O 將認證功能從應用中獨立出來,單獨進行模塊化設計、實現和維護(而不是象以
前那樣,將認證功能的代碼跟應用程序編譯在一塊);
O 為這些認證模塊建立標準API,以便各應用程序能方便的使用它們提供的各種功能

O 認證機制對其上層用戶(包括應用程序和最終用戶)是透明的。
  PAM機制由SUN設計並首先在Solaris 2.3上部分實現,後來逐漸在其他UNIX平台
上實現,包括Linux(其實現稱為Linux-PAM)。
5.5.2 PAM的結構
  PAM採用分層的體系結構。最下面是模塊層,負責實現具體的認證功能,包括帳
戶管理(account)、口令鑑別(auth)、口令管理(password)和會話管理(ses
sion)4個模塊。
  應用接口層位於模塊層之上,調用下層提供的服務,並向上(應用程序)隱藏
PAM實現的細節。
5.5.3 配置文件
/etc/pam.conf
/etc/pam.d (如果存在這個目錄,則忽略/etc/pam.conf)
  配置文件是應用接口層的另一個重要組件。其作用主要是為應用選定具體的鑑
別模塊,模塊間的組合以及規定模塊的行為。
  /etc/pam.conf的語法為每行5項(在Linux-PAM的手冊頁pam(8)中有更詳細的描
述):
service type control module-path module-arguments
  Service是服務的名字,比如login,su等。注意,/etc/pam.d目錄下面有許多
配置文件,分別對應某項系統服務,文件名即等於service,因此每行只有4項。
  Type為account,auth,password,session之一,即要使用的認證模塊。每個
應用可以使用多個認證模塊,或者說可以將模塊「堆疊」使用,但是每一行只能定
義一個,因此一項服務可以有多行配置。
  Control規定了如何處理模塊認證失敗或成功,可以是requisite、required、
sufficient或optional。
  Module-path是PAM庫文件的文件名。缺省路徑是/lib/security/。
  Module-arguments是可以傳給模塊的參數。
5.5.4 other
  特別需要指出的是,有一個特殊的服務名字——other。如果沒有明確指明應用
於某項服務的規則,就用other的定義來處理。因此,我們可以想到,系統中PAM的
最簡配置為,只有/etc/pam.d/other這一個配置文件,即可處理所有的認證請求。
下面是我們用過的一個other配置文件的例子:
[xmdong@lips pam.d]$ cat other
#%PAM-1.0
auth required /lib/security/pam_unix.so
account required /lib/security/pam_unix.so
password required /lib/security/pam_unix.so
session required /lib/security/pam_unix.so
  當然,這樣處理對系統的安全性來說是不利的,最好還是給每項服務定義單獨
的配置文件。這不過是一種簡化問題的臨時方案。

5.6 再論initrd
  在前面的5.3節中,對initrd機制已經有了比較詳細的討論。準確的說,該部分
內容來自linux-2.4/Documentation/initrd.txt 文件。但是在實踐中,我們發現其
中描述的有些方法並不適用。是新版本內核的變化造成的(內核實現與文檔不同步
),還是2.4版內核的bug,不得而知。在我查證的過程中,看到網上有不少相關的
問題和討論。遺憾的是至今我還不能確認到底是什麼原因。
  後來我又專門讀了2.2版內核中所附帶的 initrd.txt 文件。我感覺實際的情況
似乎更接近於這個老文檔的描述。我還看到一個有關的patch文件,從該文件中可以
明確看到新的initrd.txt文檔的改變。下面是該文件的開始部分(行首的-表示老文
檔有而新文檔中已經刪除,+表示新文檔中增加的內容)。
  Using the initial RAM disk (initrd)
   ===================================
  
  -Written 1996 by Werner Almesberger and
  - Hans Lermen
  +Written 1996,2000 by Werner Almesberger > and
  + Hans Lermen
  
  
  -initrd adds the capability to load a RAM disk by the boot loader. T
his
  -RAM disk can then be mounted as the root file system and programs c
an be
  -run from it. Afterwards, a new root file system can be mounted from
a
  -different device. The previous root (from initrd) is then either mo
ved
  -to the directory /initrd or it is unmounted.
  +initrd provides the capability to load a RAM disk by the boot loade
r.
  +This RAM disk can then be mounted as the root file system and progr
ams
  +can be run from it. Afterwards, a new root file system can be mount
ed
  +from a different device. The previous root (from initrd) is then mo
ved
  +to a directory and can be subsequently unmounted.
  下面我試圖將我遇到的問題和能夠確認的東西記錄一下。(後面我們分別稱新
、老文檔為initrd.txt-2000和initrd.txt-1996)
5.6.1 根到底在哪裡
  在配置使用initrd之前,首先你要清楚,系統正常運行時,根文件系統掛載在
什麼設備上(也就是說,root device是什麼——root在哪裡?)。
  我們知道,使用initrd機制的話,系統啟動時先以RAM Disk(/dev/ram0)作為
根,然後通過某種方法將根轉換到「真實的根(real-root-dev)」(之所以說rea
l,是與前面的RAM裡臨時的根比較而言)。一種常見的情形是啟動時用initrd,然
後切換到一個硬盤分區,比如/dev/hda1。
  事實上,這個根轉換不是必須的。我們完全可以就把/dev/ram0作為我們真實的
根設備。這時,系統啟動之後所有的操作都在RAM Disk中進行。當然這樣做也有一
個明顯的缺點,即無法保存數據。比如對系統配置進行的修改(象IP地址),重新
啟動之後就丟掉了。如果要保存數據,就要想別的辦法。
  LiPS目前的做法就是這一種(沒有根轉換,initrd就是真實的根)。為了在重
新啟動之後保持配置文件的修改,我們將目錄/etc鏈接到了其他非易失存儲器(例
如,一個硬盤分區,或者USB盤的分區)。
  指定根設備是通過內核參數「root=」來完成的。以GRUB引導器的配置為例:
kernel /boot/bzImage ro ramdisk_size=65536 root=/dev/ram0
initrd /boot/initrd.img
  其中 ramdisk_size=65536 說明初始RAM盤的大小為64MB,root=/dev/ram0 說
明根的位置。下面第二個例子來自一台在hda1安裝了Redhat 9的機子:
kernel /boot/vmlinuz-2.4.20-8 ro root=/dev/hda1
initrd /boot/initrd-2.4.20-8.img
  很明顯,這裡 root=/dev/hda1 指定了真實的根,其啟動過程包含根的轉換。
但是這裡沒有指定 ramdisk_size,因為initrd的缺省大小是4MB,而initrd-2.4.2
0-8.img比較小,所以用缺省值即可。
  (我們多次提到root, root filesystem, root device, 自己體會吧。)
5.6.2 linuxrc
  在initrd機制的設計中,初始RAM盤只是作為一個過渡性質的根設備,由/linu
xrc來完成操作環境準備(比如加載一些不常用的、沒有編譯進內核的驅動程序模塊
)和根轉換工作。
  Linuxrc的執行是自動的,即內核掛載initrd盤作為根,如果根下面有這個文件
(也就是/linuxrc),就執行它。(如果沒有呢?當然什麼也不做。所以linuxrc也
並不是必不可少的。)
  接下來說說linuxrc的內容。下面的例子是從initrd-2.4.20-8.img中釋放出來
的:
[root@lips initrd]# cat linuxrc
#!/bin/nash

echo "Loading jbd.o module"
insmod /lib/jbd.o
echo "Loading ext3.o module"
insmod /lib/ext3.o
echo Mounting /proc filesystem
mount -t proc /proc /proc
echo Creating block devices
mkdevices /dev
echo Creating root device
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
echo Mounting root filesystem
mount -o defaults --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
  該腳本中首先加載了支持ext3文件系統所需的模塊,然後掛載真實的根文件系
統,並進行轉換。特別需要注意的是,linuxrc腳本一般是用nash解釋執行的,而不
是通常的bash。有關nash的詳情請看手冊頁nash(8)。簡單說,nash內置實現了多數
在執行linuxrc這個階段可能用到的命令,比如mount, pivot_root, umount;而如
果使用bash,象mount等都是「外部命令」,就需要複製/bin/mount到initrd映像文
件中。實際上,在initrd-2.4.20-8.img的/bin中只有insmod和nash兩個程序(mod
probe符號鏈接到insmod):
[root@lips initrd]# ls bin/
insmod modprobe nash
  當我按照5.3.4節描述的方法測試linuxrc的時候發現,我的腳本頭兩句執行就
報錯。
mount –o ro /dev/hda11 /sysroot
cd /sysroot
  這裡我的真實的根設備是/dev/hda11,/sysroot是initrd映像中存在的一個目
錄。這兩句完全是按照該文檔的要求寫的。後來經過多次試驗才發現問題之所在。
第一,nash實現的mount命令語法與我們常用的/bin/mount並不完全兼容;第二,n
ash根本沒有實現cd命令。
  因此,可以推斷initrd.txt-2000中講linuxrc時所舉例子不是用的nash。實際
上在該文檔中根本沒有指明用什麼shell。再回頭仔細看才發現,所有例句都是在r
oot的shell命令提示符「#」後面的,那麼它用的是bash之類了。但是令人迷惑的是
,同樣在該小節中稍後出現如下例句: # exec chroot . what-follows /console >dev/console 2>&1
  為什麼用exec執行chroot呢?chroot可以在命令行直接用啊。文檔中講到,wh
at-follows可以是/sbin/init。我用nash試了下面這個句子(nash中用exec執行外
部命令):
exec chroot . /sbin/init dev/console 2>&1
  還是不行。錯誤信息:
Usage: init 0123456SsQqAaBbCcUu
  開始我還以為後面那一串是個「magic number」,後來想以Usage開頭應該是講
使用這個命令的語法。看init(8)手冊頁,果然要求給一個參數,0~6當然是運行級
別啦,試了一個init 3也還是不行。尤其搞不明白後面那些個console什麼意思。
5.6.3 根轉換機制:新的?舊的?
  前面我們多次提到了根的轉換。在initrd.txt的兩個版本中,分別描述了兩種
根轉換機制,其中2000版中稱1996版的內容已經「過時」,不推薦使用。然而事實
上要麻煩的多,事情並不總是按照預期(如文檔所述)運行。
  為了弄清楚這個問題,我進行了一系列測試。環境是這樣的:
O 使用initrd機制,已經準備好了根文件系統映像文件initrd.img,準備好了內核
bzImage;
O initrd.img的所有內容釋放到一個硬盤分區/dev/hda11,ext2文件系統;
O 在/dev/hda11上面增加一個/boot目錄,存放bzImage和initrd.img文件;
O 以/dev/ram0作為根啟動,然後以某種機制轉換到「真實的根」/dev/hda11。
  系統的引導器是GRUB,安裝在硬盤MBR,grub.conf位於/dev/hda1(也就是做測
試的實際的根文件系統)。按照上述環境配置,在grub.conf中增加如下內容:
title lips (testing ......)
root (hd0,10)
kernel /boot/bzImage ro root=/dev/hda11 ramdisk_size=65536
initrd /boot/initrd.img
  下面我們分別使用不同的/linuxrc進行了測試,以確認到底哪種機制是可行的

  第一,如果沒有/linuxrc會怎麼樣呢?
  結果是系統能夠成功啟動到以/dev/hda11作為根,並且把initrd(也就是舊根
文件系統)的內容移到了/initrd目錄。這是符合initrd.txt-1996文檔中第一段的
描述的。所以只要你使用了initrd,指定了新的根,並且準備好了/initrd目錄(已
經在/dev/hda11創建了/initrd),內核可以自動完成根的轉換工作。終端上面有如
下輸出信息:
Trying to move old root to /initrd ... okay
  這裡有個小問題,即最後/initrd沒有卸載,這意味著initrd所分配內存也沒有
釋放。因此umount /initrd不是內核自動完成的,而應該在/linuxrc中的某個位置
進行。如果linuxrc僅包含卸載/initrd的命令,如下:
#!/sbin/nash
umount /initrd
  則執行情況是這樣的:umount命令報錯(返回錯誤碼22),然後出現前面所示
Trying…的信息。結果跟前面是一樣的。因為linuxrc執行在先,當時舊根還沒有被
轉移到/initrd中來。
  如果沒有/initrd目錄會怎樣?我們把/dev/hda11上面的/initrd目錄刪除,重
新啟動(沒有/linuxrc),結果是可以啟動到以/dev/hda11為根,且看不到原來的
initrd。該過程中出現如下信息:
Trying to move old root to /initrd ... failed
Unmouting old root
Trying to free ramdisk memory ... okey
  
  第二,pivot_root可以用,但是chroot不能用。
  pivot_root是在initrd.txt-2000文檔中引入的新機制。在測試pivot_root的過
程中,除了在nash中不能用cd命令造成的困惑(這個問題前面已經說明)之外,使
用pivot_root基本上是成功的。/linuxrc腳本的主要內容如下:
#!/sbin/nash
mount -o defaults --ro -t ext2 /dev/hda11 /sysroot
pivot_root /sysroot /sysroot/initrd
  但是,用這個腳本不能啟動,造成系統掛起:
VFS: Cannot open root device 「hda11」 or 03:0b
Please append a correct 「root=」 boot option
Kernel panic: VFS: Unable to mount root fs on 03:0b
  如果按照initrd.txt-2000的指導,pivot_root之後應該執行chroot,但是我始
終沒有辦法使chroot成功執行(有關情況前面已經說明)。不過可以肯定的是,pi
vot_root執行成功之後,當前目錄就是新的根目錄。
  第三,/proc/sys/kernel/real-root-dev
  initrd.txt的新版本中最後一節專門指出,向/proc/sys/kernel/real-root-d
ev文件中echo數字的方法(稱為change_root機制)是過時的。然而令人迷惑的是,
Redhat 9的缺省安裝產生的initrd-2.4.20-8.img中(前面已經列出了其/linuxrc文
件內容),同時使用了pivot_root和change_root機制。
  測試下列/linuxrc腳本,系統可以啟動到/dev/hda11,但是/initrd沒有卸載。
如果在腳本末尾umount /initrd,會返回錯誤碼16。
#!/sbin/nash
mount -t proc /proc /proc
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
#echo 0x030b > /proc/sys/kernel/real-root-dev
mount -o defaults --ro -t ext2 /dev/hda11 /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
  雖然這樣可以啟動,但是有關real-root-dev還有幾個沒有弄清楚的問題:
  real-root-dev的值到底是什麼?
  目前我還沒有看到解釋real-root-dev的值是什麼東西的正式文檔,根據情況判
斷的話,我認為應該是該設備的「major-minor」(主、次設備號)。
  為什麼用0100而不是030b?
  如果上述判斷準確的話,那麼寫入0100就表示/dev/ram0。這就奇怪了,「真實
的根設備」應該是/dev/hda11呀,那麼是不是應該寫030b呢?但是測試發現用030b
同樣會導致不能啟動。
Kernel panic: VFS: Unable to mount root fs on 03:0b
  
5.7 提示
5.7.1 文件系統目錄層次結構
  根文件系統的目錄結構最好符合「Filesystem Hierarchy Standard(文件系統
層次標準)」[7],而不能自己隨意創建。
  順便說一下,像這種情況:/bin, /sbin, /usr/bin, /usr/sbin 這4個目錄都
可以放應用程序,具體放在哪個目錄,則要根據該應用程序在系統中的作用來確定
。一般地,系統的關鍵應用程序放在/bin,只能給超級用戶root訪問的關鍵應用程
序放在/sbin,相比之下比較次要的應用程序和root應用程序分別放在/usr/bin和/
usr/sbin。
5.7.2 mklips.sh(製作LiPS的腳本)
  複製文件的工作全部可以手工進行,但是做一個shell腳本來完成所有工作顯然
是一個更好的辦法。
  在我們的項目中,製作LiPS(也就是完成裁減Linux)的工作,除了編譯內核之
外,都可以通過mklips.sh腳本完成。
5.7.3 lips.conf(LiPS配置文件)
  lips.conf是LiPS的配置文件,由mklips.sh腳本使用,主要用來控制所製作的
LiPS系統包括哪些可選的模塊,例如:
INCLUDE_APACHE=no
INCLUDE_IPTABLES=no
INCLUDE_PROFTPD=yes
INCLUDE_NFSD=no
INCLUDE_SAMBA=yes
  通過一系列的INCLUDE_?=yes或者no,可以實現LIPS的模塊化。在mklips.sh腳
本中,判斷每個INCLUDE的值,來確定是否複製某個模塊相關的文件。
  配置文件中還可以包括其他可配置的信息。
5.7.4 cp –dpR
  複製文件請使用「cp –dpR」命令,可以保留文件的屬性(特別是對於設備節
點和符號連接等特殊文件),還可以複製整個目錄。
5.7.5 如何判斷一個程序依賴哪些文件
  除了庫文件外,關鍵是找出相關的配置文件。man手冊頁是判斷應用程序配置文
件的重要依據。我們以安裝Apache Server為例來說明判斷複製哪些文件的過程。
  首先確定其可執行文件是/usr/sbin/httpd。然後看httpd的手冊頁,即
[root@lips lips]# man httpd
httpd(8)
httpd(8)
NAME
httpd - Apache hypertext transfer protocol server
…………(略)
FILES
/etc/httpd/conf/httpd.conf
/etc/mime.types
/etc/httpd/conf/magic
/var/log/httpd/error_log
/var/log/httpd/access_log
/var/run/httpd.pid
February 1997
httpd(8)
(END)
  這時關鍵看最後一段FILES,列出了有關的配置文件、日誌文件和進程文件,那
麼我們就知道了httpd要在目標系統中運行,這幾個配置文件是必不可少的。
  把httpd和用ldd找出的庫文件以及上述配置文件複製到目標系統,運行httpd試
一下,看看是否正常。一般情況下應該沒有問題。但是httpd比較特殊,除了ldd找
出的庫文件外,它還需要很多可加載的模塊(庫)。怎麼發現呢?重要的一點是看
出錯信息(有時候還要查看日誌中的信息,/var/log/messages或者應用程序日誌)
,看httpd報告缺少什麼;還可以看看相關的配置文件httpd.conf,也能找到有用的
信息。然後我們發現需要/usr/lib/httpd這個目錄下的庫,把它也複製過去即可。

5.7.6 帶庫文件複製——lcp()
  在複製可執行文件(軟件)的過程中,如果沒有正確複製相關的庫文件,該軟
件肯定不能在目標系統中正常運行。而通過ldd命令手工確定每個軟件的庫文件,是
一個繁瑣且費時的任務。另一個隱含的缺陷是,當你不再需要某個軟件時,刪掉可
執行文件之後,相應的庫文件是否需要刪除呢?如果刪除了,而該庫文件是其他軟
件也需要的,會導致其他軟件不能用;如果不刪除,就有可能留一些垃圾庫文件在
目標根文件系統中。
  因此,最好是能夠保證每次複製可執行文件的同時自動複製相關聯的庫文件。
我寫了一個腳本函數 lcp() 來解決這個問題。語法和主要代碼如下(以#開頭的行
為註釋):
# lcp BIN BINPATH LIBPATH
# BIN:可執行文件路徑
# BINPATH:可執行文件的目標路徑(複製到哪裡)
# LIBPATH:相關庫文件的目標路徑
lcp()
# run()是另一個函數,執行它後面的shell命令,並在遇到錯誤時報錯、寫錯
誤日誌
# 首先複製BIN到BINPATH
run "$CP $BIN $BINPATH"
# 使用ldd找出與BIN相關的庫文件,把ldd的輸出送給LDDSTR
LDDSTR=`ldd $BIN`
# 循環檢查LDDSTR字符串的每一項
for STR in $LDDSTR; do
# 判斷出庫文件路徑
LIB=`echo $STR | grep "/lib/" `
if [ -z "$LIB" ]; then
continue
fi
# 複製LIB到LIBPATH,除非要複製的庫文件在目標路徑中已經存在
LIBNAME=`basename $LIB`
if [ ! -f "$LIBPATH/$LIBNAME" ]; then
run "$CP $LIB $LIBPATH"
run "cp $LIB $LIBPATH"
else
log "Warning: File "$LIBPATH/$LIBNAME" exis
t."
fi
done
}
5.7.7 庫文件的命名
  (參考資料[9]之6.2節)
  我們這裡所說的「庫」都是指的GNU C Library,也就是glibc。
  在/lib下面可以看到很多庫文件,主要分為4類:
O 實際的共享庫(Actual shared libraries)
文件名格式為 libLIBRARY_NAME-GLIBC_VERSION.so,其中LIBRARY_NAME是庫的真正
名稱,GLIBC_VERSION是glibc包的版本號。比如glibc 2.2.3版math(數學)庫的文
件名為libm-2.2.3.so。
O 主修訂版本符號鏈接(Major revision version symbolic links)
庫的主修訂版本號與glibc版本號不同。比如,glibc 2.2.3的C共享庫libc-2.2.3的
主修訂版本號為6,libdl-2.2.3為2。主修訂版本符號鏈接的命名格式為 :libLIB
RARY_NAME.so.MAJOR_REVISION_VERSION,那麼C共享庫的符號鏈接即 libc.so.6。
一個程序連接到一個庫之後,它在運行時訪問的就是這個符號鏈接。
O 版本無關的符號鏈接(Version-independent symbolic links to the major re
vision version symbolic links)
這些符號鏈接的作用是為用到某個庫的所有程序提供一個統一的入口,而不管實際
上glibc的版本或者該庫的主修訂版本。其命名格式為 libLIBRARY_NAME.so。比如
,libm.so鏈接到libm.so.6,libm.so.6又鏈接到libm-2.2.3.so。唯一的例外是li
bc.so,是個腳本。連接一個程序時用的是這個符號鏈接。
O 靜態庫文件(Static library archives)
這些庫是應用程序靜態連接用的。格式為 libLIBRARY_NAME.a.
  
  


6 引導

6.1 引導過程概述
6.2 幾種引導方式
  幾種引導方式的粗略比較如下表所示。
優點
缺點
DOC
DOM
FLOPPY
HARDDISK
NETWORK
USB-HDD
容量大,讀寫可靠
  
6.3 grub引導器
  有了前面生成的Linux內核和根文件系統映像文件後,製作引導盤非常簡單。在
動手製作引導盤之前,最好先瞭解一下grub引導器。
  Grub是一個通用的多引導加載軟件,與較早期多數Linux發行版本提供的另一個
引導器lilo相比,grub的功能更強大、設置更方便、更靈活。因此本項目選用grub
作為引導器軟件。
  本文檔不是grub的教學文檔,所以有關grub的詳細用法,請參考其他有關文檔
。這裡僅強調幾點:
O 引導盤的文件系統可以是ext2,ext3,msdos (FAT),vfat (FAT32),等等;
O grub表示硬盤、分區的方式與Linux的方式不同。Linux系統的IDE硬盤表示為/de
v/hd{a,b,c,d},SCSI設備表示為/dev/sd{a,b,c,d,…},分區從1開始編號,比如P
rimary Master IDE硬盤的第二個分區是/dev/hda2;而grub的硬盤(包括IDE和SCS
I)統一從0開始編號,分區也是從0開始編號,比如系統中的第一個硬盤是(hd0),
其第一個分區是(hd0,0)。
O 在grub的提示符下面輸入命令和參數時,按TAB鍵可以自動補全。
6.4 USB引導
  使用USB引導盤有很多好處,比如說,容量大、讀寫可靠,不佔用IDE接口,攜
帶方便等等。
6.4.1 製作步驟
6.4.1.1 創建文件系統
  首先,必須在USB盤上面創建文件系統(也就是格式化)。你幾乎可以使用gru
b支持的所有文件系統,包括常見的各種文件系統,比如ext2,ext3,FAT,FAT32等
。但是根據我的經驗,需要注意的是:
O 最好不要使用FAT,即msdos,因為FAT的文件名有「8.3」的限制,所以象「grub
.conf」這種文件名就被截斷成了「GRUB.CON」。
O FAT和FAT32都不能表示符號鏈接文件,雖然有變通的方法,即將文件再複製一份

  順便說一下在Linux下面怎麼訪問USB盤。
  如果系統中沒有其他的SCSI設備,那麼插在USB 1接口上面的USB盤的設備名為
/dev/sda,其分區為/dev/sda1。依此類推。一般插入USB盤後,窗口中會出現驅動
程序輸出的一些信息,其中有sd?的字眼。接下來就跟訪問普通的硬盤分區沒有什麼
兩樣了。
#mke2fs /dev/sda1
#mount –t ext2 /dev/sda1 /mnt
  注意:Redhat 7.3不支持Intel 845系列芯片組的主板。
6.4.1.2 複製文件
  按照下面的列表,複製文件(包括目錄結構)到USB引導盤:
備註
/boot/
bzImage
或者vmlinuz
initrd.img
/grub/
grub.conf
menu.lst
符號鏈接
stage1
stage2
6.4.1.3 安裝grub
  安裝grub到USB盤的引導扇區。假設系統有一塊IDE硬盤,這時USB盤是grub看到
的第二塊「硬盤」,所以表示為(hd1)。
#grub
grub> root (hd1,0)
grub> setup (hd1)
  root命令告訴grub,內核文件所在的位置。Setup命令安裝grub到hd1的引導扇
區,如果是setup (hd1,0),則安裝到第一個分區(即/dev/sda1)。
  上述命令序列也可以通過執行腳本完成。
6.4.1.4 用USB盤引導系統
  在用新製作的USB引導盤引導之前,還需要確認BIOS的一個設置,即第一個啟動
設備應該設置為「USB-HDD」。
  OK,插上USB盤,試一試。
6.5 提示
6.5.1 版本問題?
  我們的項目開始的時候用Redhat 7.3,但是後來做USB引導盤時發現,我們的環
境不支持USB盤。我想Redhat 7.3應該是支持USB盤的,因為我以前在7.1下面就用過
。那麼有可能是主板的問題,i845的芯片組比Redhat 7.3要新,也許是沒有該芯片
組的正確驅動。
  後來在Redhat 7.3下更新了內核,使用2.4.20版本的Linux內核即可正常支持U
SB盤。
  然而還有一個問題,Redhat 7.3的GRUB版本是0.91,在使用中發現,製作USB引
導盤沒有問題,但是一旦你改變USB盤的文件(比如複製一個新的文件上去),本來
可以引導的USB盤就不行了。
  而Redhat 9.0使用的是GRUB 0.93,就沒有上述問題,並且使用USB盤也沒有問
題。也就是說,使用Redhat 9就可以了。不過Redhat 9集成的其他很多軟件也有變
化,比如Apache升級到了2.0版本,以前的httpd.conf配置文件要修改過之後才能正
常使用;另外quota接口也有變化。
  因此改變版本需要一定的代價,究竟使用什麼版本應該綜合考慮,最好在項目
開始時就做出正確的選擇,並保持穩定。
  
  


7 遠程串口控制台

7.1 概述
  
7.2 配置方法
7.3 提示
7.4 Linux 遠程串口控制台指南
  (這是我以前寫的一份簡單的文檔,曾經貼到網上,附在這裡供參考)
  Linux 遠程串口控制台指南
  
  dot
  Dec 27, 2002
  
  2002年聖誕節期間,我在 Redhat Linux 7.0 (kernel 2.2.16-22) 平台上配置
了遠程串口終端,整個過程基本順利,但是也經歷了一些意想不到的波折,幸好最
終是成功了的。乘著記憶還比較清晰的時候,寫下這篇文檔,以供自己和他人參考

  
  首先參考 "Linux-Remote-Serial-Console-HOWTO",該文檔已經足夠詳盡,按
要求一步步地做即可。該文檔描述的是 Redhat 7.2 平台,個別地方跟 7.0 有些差
異,不過問題不大。
  
  要注意的問題主要是:
  
  * 串口直連電纜
  
  開始我並沒有在意這個問題,我手頭上有一根以前做的直連電纜,是只用了3根
線的那種(2、3交叉,5對接),因此 HOWTO 文檔中講電纜製作的章節我就跳過去
了,沒有仔細看,以為我這根電纜就可以了。事實也給人以這種假相:當我按照文
檔的說明完成了配置文件的修改,重新引導 Linux 機子,這時在 Windows 的超級
終端中確實顯示了所有該顯示的信息,看起來沒問題。然而接下來配置 getty 時就
不行了,應該出現在超級終端中的 login: 提示符死活不肯出現。以為是 getty 軟
件的問題,先後測試了 getty 和 mgetty,都不行。後來在 quickmouce 的提醒下
,又仔細看文檔,按照 11.3 節的圖 11-1 重新製作了串口直連電纜,才解決問題

  
  * getty 軟件
  
  HOWTO 文檔中已經指出,mingetty 不支持串口終端,所以這個軟件要首先排除
(mingetty 的手冊頁中也有相關說明)。而 Redhat 缺省安裝的就是這個軟件,所
以要重新下載安裝其他的 getty 類軟件。文檔中也已經列出了幾種常用的 getty
的變種。
  
  來說說 mgetty 先。為什麼我先使用了這個軟件呢,一是因為 Redhat 7.0 的
安裝盤上面有它的 RPM 包,直接拿來裝很方便,另外是因為 mingetty 的手冊頁中
推薦使用 mgetty 。結果是 mgetty 運行後在日誌文件中報告大量錯誤,莫名其妙
。我想可能是這個光盤上的版本老了,於是上網下載了比較新的版本 mgetty-1.1.
25-5.i386.rpm ,運行之後情況好多了,似乎要成功的樣子。在沒有使用新的串口
線之前,login: 出不來,但是在超級終端中敲的字符 mgetty 可以收到(從日誌中
看的出來);換了新製作的串口線之後,第一次!成功了,一切都像預期的那樣,
我可以從超級終端登錄。可是當我退出想再登錄一次,就不行了,甚至我把兩台機
子全部重啟也不行啦。我又試用 Linux 的 minicom 終端來連接,也是只成功了一
次,就再也不行了。真是怪哉,腦袋都快想破了,也不知道是為什麼。後來終於懷
疑 mgetty 有問題,換了其他的,天哪,終於解脫了。不知道後面更新的版本是否
可以,我是沒有勁去試了。
  
  再來說說 agetty 。其實沒有什麼好說的,因為我根本沒有用過這個。我本來
想試一下的,但是從網上下載安裝太麻煩了。下載了 agetty-2.11w-2.i386.rpm ,
安裝時 RPM 說要先安裝 login 包,然後又要求什麼 pam 包,然後又需要 awk ,
真是 faint 了,太麻煩了,所以最終我也沒有安裝它。
  
  最後說 getty 啦。也就是 HOWTO 文檔中所謂的 「傳統」 getty 。我下載的
RPM 包的名字叫 getty_ps-2.0.7j-9.i386.rpm 。當我正在為 mgetty 的問題頭疼
的時候,換成它之後就一切 OK 了。
  
  * 終端軟件
  
  Windows 下面可以用超級終端、NetTerm,Linux 下面有 Minicom 。都比較好
用,注意參數配置與目標機的串口一致。
  
  * 修改過的配置文件列表
  
  /etc/lilo.conf
  /etc/inittab
  /etc/gettydefs
  /etc/securetty
  /etc/makedev.d/linux-2.2.x
  /etc/security/console.perms
  /etc/sysconfig/init
  /etc/sysconfig/kudzu
  
  * 再談串口直連電纜
  
  這次調試在串口直連電纜上面花費了不少力氣,對它們的瞭解也增加了不少。
以前以為直連電纜就是接 3 根線,其實不然。只用了 2、3、5 引腳的直連電纜不
能提供握手信號,因此如果軟件需要使用 CTS/RTS 或者 DTR/DSR 流控,就需要連
接更多的引腳。
  
PC DB9 DB9
-------------------- -----------------------
RxD Receive Data 2 <----- 3 TxD Transmit Data
TxD Transmit Data 3 -----> 2 RxD Receive Data
|--> 6 DSR Data Set Ready
DTR Data Terminal Ready 4 --|--> 1 DCD Carrier Detect
GND Signal Ground 5 ------ 5 GND Signal Ground
DCD Carrier Detect 1 <--|
DSR Data Set Ready 6 <--|-- 4 DTR Data Terminal Ready
RTS Request To Send 7 -----> 8 CTS Clear To Send
CTS Clear To Send 8 <----- 7 RTS Request To Send
RI Ring Indicator 9 (not used)
  
  上面是兩端都是 DB9 接頭的標準 NULL MODEM 電纜的接線圖,可以提供全部握
手信號。這也是 Remote-Serial-Console-HOWTO 中要求的直連電纜做法。我做通串
口控制台使用的就是這種電纜。
  
  如果你打算自己製作電纜,就會發現一些問題。我們一般利用網線(雙絞線)
來做,這種雙絞線是 8 芯的,而按照圖示的連接方法則需要 9 根線。因此最簡單
的方法是用那種很多芯的排線來做,需要多少根割多少根(最好是彩色的,不容易
弄混)。後來我想,我們用到的其實就是 CTS/RTS 流控信號,到 2000 年為止 Li
nux 還不支持 DTR/DSR 流控,應該用不了這麼多線。於是我就用網線做了根不完整
的直連電纜:2、3 交叉,5 對接,7、8 交叉,還空 3 根線,就把 1、4 也交叉連
上了,結果是用了 7 根線,還空 1 根,與上面比只是少了 4、6 交叉,也就是沒
有 DTR/DSR 信號。事實證明這樣也是通的。我猜想 1、4 交叉不要應該也是通的,
只是沒有試過,已經焊上去懶得再弄了。
  
  關於串口方面的更多內容可以參考 "Linux-Text-Terminal-HOWTO" 和 "Linux
-Serial-HOWTO" 文檔。
  
  * 為什麼要用串口終端(控制台)?
  
  為什麼費勁做這個 Serial Console 呢?最容易想到的理由是省錢,呵呵,省
掉了顯卡、顯示器、鍵盤,只剩下一個 "Box",多好玩。
  
  說正經的,這種做法在嵌入式系統的開發中也是很有價值的。現在很多人都在
利用 X86 平台做嵌入式系統開發,甚至做產品。我曾經測試過清華某某做的 foob
ar 服務器,鏡像光盤用的,賣給你的就是一個主機,我自己給接上顯示器、鍵盤,
開機就是 Linux ,還可以進入單用戶模式,兩分鐘就把 root 口令改了,你說這樣
的服務器有什麼安全性可言?如果能夠屏蔽本地控制台,配置串口終端,不是更「
象」一個產品嗎?
  (完)




8 系統安裝光盤

8.1 概述
  本節介紹一種系統安裝光盤的製作方法。安裝光盤用於產品階段的生產安裝。
因此該安裝光盤必須是可引導的、簡單好用,並且一般不包含源代碼。
  製作可引導光盤的方法有很多種,我們用了一種最簡單的方法,就是拿來一個
可引導光盤的ISO映像,然後做必要的修改以滿足我們的要求。
  請準備Redhat 9的第一張安裝光盤,我們將要用到的文件是 /images/boot.is
o。(其他發行版本應該也可以,只要原理是一樣的。)
  另外如果你的工作平台是Windows,請準備WinISO 5.3軟件,用來編輯光盤ISO
映像文件。
  當然如果你要燒盤測試的話,還要準備刻錄機和CD-RW或者CD-R光盤。
8.2 boot.iso光盤的文件結構分析
  用WinISO打開boot.iso即可看到該光盤的文件(其實Redhat 9第一張安裝光盤
的/isolinux目錄就是boot.iso解開後的內容)。下面是文件列表:
[xmdong@lips isolinux]$ ls
boot.cat initrd.img options.msg snake.msg vmlinuz
boot.msg isolinux.bin param.msg splash.lss
general.msg isolinux.cfg rescue.msg TRANS.TBL
  其中關鍵的文件是boot.cat,initrd.img,isolinux.bin,isolinux.cfg和vm
linuz;isolinux.cfg是如何引導的配置文件,我們主要修改這個文件即可;initr
d.img和vmlinuz分別是初始化RAM盤和內核,其作用在前面章節中已經詳細描述過;
另外兩個文件是光盤引導需要的,不動它。
  其餘的*.msg文件是一些引導過程中可能會顯示的文本信息,可以不管;splas
h.lss是引導時顯示的一個圖片,也可以不管。
  下面來看看isolinux.cfg的內容。
default linux
prompt 1
timeout 600
display boot.msg
F1 boot.msg
F2 options.msg
F3 general.msg
F4 param.msg
F5 rescue.msg
F7 snake.msg
label linux
kernel vmlinuz
append initrd=initrd.img
label text
kernel vmlinuz
append initrd=initrd.img text
label expert
kernel vmlinuz
append expert initrd=initrd.img
label ks
kernel vmlinuz
append ks initrd=initrd.img
label lowres
kernel vmlinuz
append initrd=initrd.img lowres
  這個配置文件的語法結構跟其他引導器的配置文件,比如grub.conf或者lilo.
conf,非常類似,比較好懂。如果再對照光盤引導安裝Redhat的實際過程看一下,
基本上不需要什麼解釋就可以理解。其中以label開頭的每個小節是一種引導配置,
缺省(或者timeout後)以label linux引導。每個配置的第一句,kernel指定引導
所用的內核,第二句append指定內核引導參數(主要說明initrd文件的位置,以及
其他參數)。
8.3 製作步驟
1) 複製boot.iso,用WinISO打開;
2) 解放出isolinux.cfg文件,並從光盤映像中刪除之;
3) 修改配置文件isolinux.cfg;
4) 製作bzImage和initrd.img,這兩個文件用於光盤引導至一個比較正常的Linux系
統下,包括常用的工具軟件和服務,我們要在這個環境下進行產品的安裝;
5) 將修改後的isolinux.cfg以及initrd.img,bzImage加入光盤;
6) 準備一個setup目錄,將產品安裝需要的文件和腳本放在這個位置,然後將setu
p目錄加入光盤;
7) 刪除沒有用到的文件,也可以不管,除非加入文件時遇到衝突,必須先把原來光
盤上的文件刪除或者改名;
8) 存盤退出,刻錄光盤。
  下面是一個修改後的isolinux.cfg配置文件的例子,很簡單:
default linux
prompt 1
timeout 600
label linux
kernel bzImage
append initrd=initrd.img ramdisk_size=65536 root=/dev/ram0
  
  
9 源代碼(配置文件和腳本)
9.1 lips.conf
9.2 mklips.sh

沒有留言: