想參與linux社區開發的進來

火星人 @ 2014-03-26 , reply:0



Magic Linux開發入門指南(一)    製作一個Linux發布難嗎?
    很難。
    製作一個Linux發布版需要很高深的技術嗎?
    你能行。

    好多人很想參與Magic Linux的開發,但多數不知從何入手。
    其實很簡單,你只需要一台供你支配的386以上配置且能夠上網的電腦,
以及一個能夠工作在其上的gcc環境。
    對,這就夠了,其他的軟體都是在幫助你更快的、更簡便的完成這個工
作。因為Linux源自於網路,發展於網路,能夠上網才能得到Linux;Linux
自身及在其之上運行的大多數軟體都是以源代碼方式提供,且非gcc不能完成
內核的編譯。擁有了這些,你就可以開始將這些源代碼轉化為可運行的內核、
Shell和一些應用軟體,一點一點的就構成了一個完整的可用的Linux系統。
    本文就是講述如何開始這些工作的。我會假定你對Linux有一定的了解,
使用過如:cp、mv、rm等常用命令,曾經成功的在某個Linux系統中安裝過某個
以源代碼形式發布的軟體,有一些C/C++或其他語言的經驗。
    另外,我所提到的gcc環境並不是單指gcc本身,而是一些與gcc相交織的
軟體集合,它們共同工作,完成從源代碼到可執行程序的轉換過程,這個過程
一般被稱之為創建。

第一章 工具鏈的製作

    在正式開始前,我還要讓你了解一個重要的知識,那就是編譯器、連接器
和程序庫他們三者之間的關係,如果你已經非常了解了,可以略過這些內容。
編譯器只是將源代碼翻譯成對應的機器代碼,但是這個時候這些代碼是不能執
行的,因為既沒有排列好執行順序也沒有指定從哪裡開始;程序庫實現了一些
程序必要的行為,比如你要輸出一些內容到屏幕或從鍵盤獲得輸入等;連接器
將編譯器產生的機器代碼進行排序並告訴計算機(嚴格來講是操作系統)從什麼
地方開始執行,當程序需要輸出一些內容到屏幕或從鍵盤獲得輸入時,請求程
序庫完成這些事情。雖然這些說法顯得很不專業,但是足以幫助你理解它們三
者之間的關係了。如果要獲得更為專業、詳細的知識請閱讀相關專業書籍。
    一個能夠正常工作的gcc環境,需要三個源代碼包的支持:binutils、
gcc和glibc,它們分別提供了連接器、編譯器和程序庫。其實他們並不僅僅提
供了這些內容:
    binutils是一個二進位工具集合,包含了彙編器、反彙編器、連接器、
elf可執行文件分析器等重要工具,這些工具在進行Linux各種應用的開發時,
發揮著巨大的作用。你可以在/usr/bin目錄中找到他們。
    gcc是一個編譯器集合,包含了C、C++、Objective-C、Fortran、Java和
Ada語言,同時為這些語言提供了一些標準庫,如:libstdc++、libgcj,……。
gcc的C是Linux的標準編譯器,linux內核完全依賴於gcc,其他編譯器不能編譯
linux內核。由於ABI(Application Binary Interface)的不兼容,其他編譯器
也不適合Linux上的大多數軟體的編譯,尤其那些使用C++作為開發語言的軟體系
統。目前Intel C/C++編譯器開始兼容gcc的ABI,因此現在可以採用Intel C/C++
編譯器創建Linux上使用C/C++開發的軟體系統,但內核不行。gcc被安裝在
/usr/bin、/usr/lib和/usr/include目錄中。
    glibc是提供系統調用和基本函數的C庫,比如open,malloc,printf等等,
所有動態連接的程序都要用到它。它是用戶程序與內核交流的標準介面。
    這三個包在一起相互作用,來完成Linux的所有創建任務。除了glibc是自包
含(自己依賴於自己)的外,其他兩個都要依賴於glibc,同時glibc會與具體的內
核版本有一定的依賴性,但這並不是絕對的。注意,他們都是用gcc編譯,並用
binutils的連接器進行連接的。這裡就比較有趣了,是先有雞還是先有蛋呢?計
算機的發展史咱們就不必討論了,在本章會詳細介紹如何來讓他們的代碼執行起
來。但他們不是我們要的全部。

    首先,你應該保證你有可用的gcc環境,能夠用它讓你的源代碼變成可執行程
序。往往這需要你的計算機運行了某個版本的Linux發布。當然Windows也行,不
過會比較麻煩,我不建議你這麼做,我也不會在這裡討論該怎麼做。你也不要指
望你現在的這個gcc環境可以直接創建Magic Linux的所有,最後你得到的還是屬
於你現在使用的這個發布。因為你現在的gcc創建產生后的程序,還是依賴於你現
有Linux發布版的glibc的。如果你說你現在就創建一個glibc不就行了嗎?不信你
可以試試,當你安裝完后,看看你的系統還能工作不?言歸正傳,你現在急需的
是能夠幫助你產生MagicLinux的gcc。

1.準備環境
    最好能在你的硬碟上劃分出一個獨立的分區,1G大小就夠了。不過這個你都嫌
麻煩的話,你有1G以上的自由空間也行。現在我假設你劃分了一個獨立的分區。
    來吧,創建/mnt/ml目錄,並將你的新分區掛接到這上面(如果不了解掛接的話,
先找找資料,google一下mount)。

#mkdir /mnt/ml
    #mount /dev/hda6 /mnt/ml (我假設你的新分區設備名為hda6)

cd到/mnt/ml目錄並創建toolchain目錄。

    #cd /mnt/ml
    #mkdir toolchain

在你的根目錄創建一個連接到toolchain上(如果不了解,google一下ln)。

    #ln -sv /mnt/ml/toolchain /toolchain

創建sources目錄。

    #mkdir sources

將binutils、gcc和glibc等的源代碼複製到sources目錄中。你可以在網路上找到它們,
google一下就行了。binutils的最新本版是2.18,源代碼包可能是這樣的文件名:
binutils-2.18.tar.bz2;gcc的最新本版是4.2.2,源代碼包可能是這樣的文件名:
gcc-4.2.2.tar.bz2;glibc的最新版本是2.7,源代碼包可能是這樣的文件名:
glibc-2.7.tar.bz2。
修改PATH環境變數。

    #export PATH=/toolchain/bin:$PATH

PATH環境變數指定了shell命令的默認搜索路徑。我們修改PATH環境變數使得在你的gcc
可用時,默認執行的是它,而不是系統自帶的。
    環境已經準備好了,我們開始吧。

2.創建新的gcc環境
    為了創建完全獨立於你現有系統的gcc環境,我們要創建兩次binutils和gcc。他們創
建的次序是很重要的。我們現在進行第一次創建。進入sources目錄。

    #cd sources

2.1創建binutils
    首先創建binutils,是因為在創建gcc和glibc時,它們會檢測連接器和彙編器,以便決定
它們能夠開啟那些特性。整個過程大概需要5分鐘(根據你機器的處理能力會有很大的不
同),佔用200MB左右的磁碟空間。
    解壓縮源代碼包,並進入解壓后的目錄:

    #tar -jvxf binutils-2.18.tar.gz
    #cd binutils-2.18

由於binutils在某些時候會有一點小問題,要修復它,需要下在一個補丁,對應2.18版本的
補丁是:binutils-2.18-configure-1.patch。

    #patch ?Np1 -i ../binutils-2.18-configure-1.patch

binutils的文檔說應該在一個獨立的目錄中創建binutils。那就創建一個build目錄。

    #mkdir build
    #cd build

現在為創建binutils做準備工作:

    #CC=」gcc -B/usr/bin/」../configure \
    --prefix=/toolchain --disable-nls --disable-werror

各選項的含義是:
    CC=」gcc -B/usr/bin/」
告訴gcc使用你當前操作系統/usr/bin目錄下的連接器。這個對於某些你使用的Linux
    發布是很重要的,因為新創建的連接器ld可能與它所提供的gcc不兼容。
    --prefix=/toolchain
    這個參數告訴configure腳本,把binutils軟體包中的程序安裝到/toolchina目錄中,也就是
    /mnt/ml/toolchain。
    --disable-nls
    這個參數禁止了國際化(通常簡稱i18n)。此時根本不需要國際化支持。
    --disable-werror
    這個參數可以防止由於你的系統提供的gcc在產生警告事件時停止創建過程。
準備好了,我們可以創建了:

    #make

創建完成後,安裝:

    #make install

別著急,還沒完事。還得調整一下:

    #make ?C ld clean
    #make ?C ld LIB_PATH=/toolchain/lib

make參數的含義是:
    -C ld clean
    告訴make,刪除所有子目錄ld中編譯生成的文件。
    -C ld LIB_PATH=/toolchain/lib
    這個選項重新編譯ld子目錄中的所有文件。LIB_PATH是Makefile的一個變數,
    在命令行里制定他,可以覆蓋默認值,並讓它指向/toolchain/lib目錄。這個變數
    的值指定了連接器的預設庫搜索路徑。
手工將新的程序複製到/toolchain/bin目錄:

    #cp ?v ld/ld-new /toolchain/bin

好了,binutils創建完成了,你現在可以刪除build目錄了。但是不要刪除binutils-2.18目
錄,因為還要編譯一次呢。退回到sources目錄,準備gcc的創建工作。

    #cd ../
    #rm ?rf build
    #cd ../

2.2 創建gcc
    連接器準備好了,但我們這次先不使用它,沒有這個必要,因為我們還需要再次
創建gcc的,那時再用也不遲。這個過程大概會花費你50分鐘的時間和650MB的磁碟空
間。
    解壓縮gcc的源代碼包並進入源代碼目錄。

    #tar ?jvxf gcc-4.2.2.tar.bz2
    #cd gcc-4.2.2

gcc與binutils一樣,建議你在一個獨立的目錄中創建它。創建build目錄。

    #mkdir build
    #cd build

為創建gcc做準備。

    #../configure ?prefix=/toolchain ?with-local-prefix=/toolchain \
    --disable-nls ?enable-shared ?enable-languages=c

各選項的含義是:
    CC=」gcc -B/usr/bin/」
    告訴gcc使用你當前操作系統/usr/bin目錄下的連接器。也就是不使用你剛創建完
    的那個連接器ld。這也是為了避免一些麻煩,可以參考創建binutils時對該選項的
    說明。
    --with-local-prefix=/toolchain
    默認情況下,gcc會搜索兩個include目錄,一個是其安裝目錄下的include,這裡是
    /toolchian/include,另外一個是/usr/local/include。這個選項就是將/usr/local/include這個默
    認搜索目錄刪除,而還是指向/toolchain/include。
    --enable-shared
    這個選項是為了創建出libgcc_s.so.1和libgcc_eh.a文件,因為下一個要創建的glibc需要
    libgcc_eh.a,要是沒有它就不會產生正確的結果。
    --enable-languages=c
    因為gcc是一個編譯器集合,這個選項指定要創建何種語言的編譯器。此時只需要C,
    那就沒什麼可說的了。
準備好了,我們可以開始創建了:

    #make

創建完成,安裝:

    #make install

最後你還應該創建一個符號連接cc到這個新的gcc,因為好多時候會用cc而不是gcc,這是為
了與Unix平台保持一致,便於程序的移植。

    #ln ?vs gcc /toolchain/bin/cc

好了,gcc創建完成了,接下來的創建過程會自動使用這個gcc的,因為你修改了PATH環境變
量。做些首尾工作,要不然你的磁碟可能吃緊了。

    #cd ../
    #rm ?rf build
    #cd ../

2.3創建glibc
    前面我說過,glibc是自包含的,不會依賴於那個軟體包。但是我也說過,它是用戶程序與
內核交流的標準借口,因此對內核還是有一定依賴的。但是這並不相矛盾,因為只要是一個系
列的內核,基本上是沒多少關係的,比如現今的2.6系列,它們會有提供統一的系統調用。
    glibc需要了解內核的系統調用和這些調用相關的一些數據結構。Linux內核做得很好,不需
要有內核的二進位文件,一切都包含在了內核的公用頭文件中了。這裡說些題外話,如果你夠
牛的話,其實完全可以不用glibc,只利用這些頭文件就可以寫出合適的用戶程序的,甚至比利
用glibc的更為優秀。不過如果你的確那麼牛,這篇文章也就不適合你了。
    不多說了,下載一個內核源代碼到你的source目錄吧。最新的是2.6.23.12。
解壓縮內核源代碼包並進入源代碼目錄:

    #tar ?jvxf linux-2.6.23.12.tar.bz2
    #cd linux-2.6.23.12

安裝相關的頭文件:

    #make mrproper
    #make headers_check
    #make INSTALL_HDR_PATH=dest header_install
    #cp ?rv dest/include/* /toolchain/include
    #cd ../

關於內核操作有什麼不了解的,可以使用make help命令獲得幫助。
解壓縮glibc的源代碼包並進入源代碼目錄:

    #tar ?jvxf glibc-2.7.tar.bz2
    #cd glibc-2.7

與gcc一樣,還需要單獨的目錄來創建,建立build目錄:

    #mkdir build
    #cd build

由於glibc不再支持i386體系了,因此它的開發者們建議在創建glibc是,最好使用-march=i486編譯選
項。的確如此,如果你不指定這個選項,會創建失敗。但是畢竟現在i486用的已經很少了,我們
也可以不考慮兼顧,為了進一步提高性能,我建議使用-march=i686編譯選項。你可以通過下面的
命令完成這些:

    #echo 「CFLAGS += -march=i686」 > configparms

接著,為創建glibc做準備工作:

    #configure ?prefix=/toolchain ?disable-profile ?enable-add-ons \
    --enable-kernel=2.6.0 ?with-binutils=/toolchain/bin ?without-gd \
    --with=headers=/toolchain/include ?without-selinux

各選項的含義如下:
    --disable-profile
    忽略掉profiling信息相關的庫文件創建,這個時候一般不需要。
    --enable-add-ons
    這個指示glibc使用附加的NPTL(本地POSIX線程庫)包作為線程庫。
    --enable-kernel=2.6.0
    告訴glibc要支持2.6.x內核。
    --with-binutils=/toolchain/bin
    這個參數並不是必要的,只是為了防止在創建glibc時用錯了binutils程序。這裡保證使用剛才創建
    好的binutils。
    --without-gd
    保證不生成memusagestat程序,這個程序會產生對你現有系統的依賴。
    --with-headers=/toolchain/include
    這個選項就是告訴glibc,使用剛剛安裝的內核都文件創建自己。
    --without-selinux
    不提供SELinux特性的支持,因為toolchain是不需要的。
在這個階段你要是看到下面的警告你就不用管它,跟你沒有任何關係,也不會有什麼影響的。

    configure: WARNING:
    *** These auxiliary programs are missing or
    *** incompatible versions: msgfmt
    *** some features will be disabled.
    *** Check the INSTALL file for required versions.

創建軟體包:

    #make

在安裝glibc的過程中,它會警告缺少/toolchain/etc/ld.so.conf文件。其實沒什事,不會有什麼影響,只要提
供一個空文件它就閉嘴了:

    #mkdir ?v /toolchain/etc
    #touch /toolchain/etc/ld.so.conf

一切順利就可以安裝了:

    #make install

恭喜你,又幹了一件了不起的事情,不過別忘了收尾阿,空間有限。

    #cd ../
    #rm ?rf build
    #cd ../



Magic Linux開發入門指南(二)2.4 讓這個新的gcc環境能夠真正的工作起來

    編譯器、連接器、程序庫都創建好了,可以開始創建MagicLinux了吧?呵呵,不行!這個
新的gcc環境還沒有真正工作起來呢。不信,我們做一個實驗試試。編寫一個最簡單的C代碼:

    #echo 'main(){}' > ttt.c
    #gcc ttt.c
    #readelf -l a.out

看看結果,是不是有一行類似下面的內容:
    [Requesting program interpreter:/lib/ld-linux.so.2]
這是不對的。readelf是分析elf可執行文件(Linux下可執行文件的格式)格式的工具,-l選項是
用來顯示可執行文件各段頭內容的,通過它可以了解一個可自行文件的依賴關係。上面的結果
表明新的gcc產生的可執行文件還是依賴於你現有系統的ld-linux.os.2,這是glibc的一部分。
這是為什麼?該怎麼辦?
    問題在創建binutils是就已經作了一些解決,但是還沒有完全解決。回想一下,在安裝完
binutils后,還做了如下操作:

    #make -C ld clean
    #make -C ld LIB_PATH=/toolchain/lib
    #cp -v ld/ld-new /toolchain/bin

創建了一個ld-new,而且還複製到了/toolchain/bin下,這個ld-new就是關鍵,執行下面操作:


    #mv -v /toolchain/bin/{ld,ld-old}
    #mv -v /toolchain/$(gcc -dumpmachine)/bin/{ld,ld-old}
    #mv -v /toolchain/bin/{ld-new,ld}
    #ln -sv /toolchain/bin/ld /toolchain/$(gcc -dumpmachine)/bin/ld

這就使得接下來創建的程序都使用/toolchain/lib中的程序庫了。可是為什麼要現在才作上述
操作呢?因為在這之前,glibc還沒有被創建,/toolchain/lib還不存在。
    連接器搞定了,編譯器還不行呢。這裡我要多說幾句。程序庫分為兩種,即靜態庫和動態
庫。靜態庫就是在程序在被創建時由連接器確認它們的關係,並將它們組合在了一起成為一個
整體;動態庫則不同,是在程序運行時,由動態連接器確認它們之間關係,它們是完全獨立的
個體。這裡不要將連接器和動態連接器弄混了,連接器是binutils提供的ld程序,而動態連接
器則是glibc提供的。連接器的名稱通常是 ld-linux.so.2,在不怎麼流行的平台上則可能是
ld.so.1,而在新的64位平台上更可能是別的完全不同的名稱。為什麼這時候編譯器還不行呢?
因為編譯器為了創建不同的程序,即要使用連接器也要使用動態連接器,所以要還要告訴編譯
器動態連接器在哪裡。現在的這個gcc還只是知道你所用系統的動態連接器的位置,你現在應
該告訴他新的在哪裡。這是通過gcc的specs文件完成的。
    通過下面的指令來產生gcc的specs文件:

    #gcc -dumpspecs > `dirname $(gcc -print-libgcc-file-name)`/specs

直接將specs文件放入了它所起作用的位置。可以執行下面的命令獲得這個路徑:

    #dirname $(gcc -printf-libgcc-file-name)

打開spces文件,修改所有類似「/lib/ld-linux.so.2」內容為
「/toolchain/lib/ld-linux.so.2」。你可以用任何你熟悉的方式作,我有一個簡單的方法如
下:

    #gcc -dumpspecs | sed 's@/lib/ld-linux.so.2@/tools&@g' \
    > `dirname $(gcc -print-libgcc-file-name)`/specs

這幾個程序簡單的組合,利用管道和輸出從定向機制,就完成了所有的操作。這就是類Unix系
統的精髓與魅力所在,各位讀者體會一下,如果想了解更多Unix精髓,建議看一下《Unix編程
藝術》一書。
    動態連接器問題解決了,還有一些麻煩問題需要處理,要不然,這個新的gcc環境還是對你
現在運行的系統有關係,因為gcc的fixincludes腳本在創建gcc的過程中,由於某些原因把你系
統里的頭文件複製給這個新的gcc環境中去了。這就是好心辦壞事,不過不用擔心,是有辦法挽
救的。執行下面的命令會將fixincludes產生的影響處理掉,當然,如果fixincludes沒有幫倒
忙,下面的命令也不會作壞事,破壞這個新生的gcc環境:

    #GCC_INCLUDEDIR=`dirname $(gcc -print-libgcc-file-name)`/include
    #find ${GCC_INCLUDEDIR}/* -maxdepth 0 -xtype d -exec rm -rvf '{}' \;
    #rm -vf `grep -l "DO NOT EDIT THIS FILE" ${GCC_INCLUDEDIR}/*`
    #unset GCC_INCLUDEDIR

這下好了,馬上檢測一下:

    #gcc ttt.c
    #readelf -l a.out

如果你能看到如下結果就證明成功了:
    [Requesting program interpreter:/lib/ld-linux.so.2]
如果沒看到這樣的結果,沒辦法了,從新創建gcc吧。注意查看一下你現在的PATH環境變數,是
否與「準備環境」一節相符。
    最後,應該收一下尾了。

    #rm -v ttt.c a.out


2.5 繼續工作

    這個時候你的全新的gcc環境可以工作了,但是我們前面說過,還需要再創建一次binutils
和gcc,這是因為你的binutils和c編譯器還沒有脫離你現有的系統,同時gcc也只支持c編譯,
只是臨時的過度產物。現在就要開始真正的工作了,這次創建的binutils和gcc真正的與你的系
統脫離了,而且你要用它們來完成接下來很多重要程序的創建工作。
    這次的創建如此之重要,你需要保證創建完成的binutils和gcc可以很好的工作。不要以為
你可以憑藉經驗作到這些,或者手工編寫一些簡單的程序測試一下,這是一個浩大且複雜的工
程。你真正需要的是一些現有的工具,來檢測你創建完成的程序是否能用。你也不用擔心這些,
幾乎每個重要的開源軟體都包含了測試套件,但是這些套件需要一些工具的支持,所以,你在
第二次創建binutils和gcc之前,要準備好這樣的工具。它們是Tcl、Expect和DejaGNU,它們
為大多數軟體的測試套件提供了支持環境,所以不管怎麼樣,我都要建議你創建它們。
    Tcl,呵呵,和你家的電視機沒什麼關係。Tcl是Tool Command Language的簡稱,即工具
命令語言。Tcl是一個種很通用的腳本語言,它幾乎在所有平台上都可以解釋運行,功能強大。
首先,Tcl是一種簡單的腳本語言,主要用於發布命令給一些交互程序,如文本編輯器、調試器、
Shell等;其次,Tcl是一個庫包,可以被嵌入應用程序,Tcl的庫包含了一個分析器,不但用於
執行內建命令的常式,還可以使用你擴充(定義新的過程)的庫函數。
    Expect是Tcl的一個擴展,為某些交互程序提供了自動交互功能。現代的Shell對程序提
供了最小限度的控制(開始、停止等),而把交互的特性留給了用戶。這意味著有些程序你不
能非交互的運行,比如說passwd。有一些程序可以非交互的運行,但在很大程序上喪失了靈活
性,比如fsck。這表明Unix的工具構造邏輯開始出現問題。Expect恰恰填補了其中的一些裂痕,
解決了在類Unix環境中長期存在著的一些問題。不僅如此,不管程序是交互的還是非交互的,
Expect都能運用。這是一個小語言和類Unix系統的其他工具配合起來產生強大功能的經典例子。
    DejaGNU是一個測試程序框架,如果這麼解釋你不明白的話,可以說成是Framework,如
果還不能明白,可以說DejaGNU有點類似MFC,但是它們實現的語言和目的不同。DejaGNU就是
為前面所說的測試套件提供了一個統一的框架,它也是Tcl的一個擴展。
    另外,補充一句,大部分軟體包,都會包含測試工具的,建議你執行以下,這樣可以保證
你發布的系統有很好的可用性。
    沒什麼可說的,創建它們吧。

2.6 創建Tcl

    目前最新版本的Tcl是8.5.0,但是Expect還沒有跟上腳步,所以建議使用8.4.17。源代碼
包可能是這樣的名字:tcl8.4.17-src.tar.gz。創建Tcl大概需要5分鐘左右的時間,佔據24MB
左右的磁碟空間。
    解壓縮源代碼包,並進入源代碼目錄:

    #tar -zvxf tcl8.4.17-src.tar.gz
    #cd tcl8.4.17

現在為創建Tcl作準備工作:

    #cd unix
    #./configure --prefix=/toolchain

開始創建:

    #make

安裝:

    #make install

為了讓Tcl的一些擴展程序能夠被創建,還需要安裝Tcl的頭文件,執行下面的操作:

    #make install-private-headers

為了兼容性,還需要創建一個符號連接,如下:

    #ln -sv tclsh8.4 /tools/bin/tclsh

Tcl創建完畢了,可以進行下一步的操作了。別忘了收尾工作:


    #cd ../../
    #rm -rf tcl8.4.17

    另外,如果你對這個剛剛創建的Tcl有些不放心的話,在執行安裝步驟之前可以測試一下:

    #TZ=UTC make test

這個過程不是必需的,因為Tcl的測試程序在某些環境下會失敗,而且這個測試也並不是很關
鍵。TZ=UTC 參數將時區設置為協調世界時(UTC),也就是格林尼治時間(GMT),但只是在運行
測試程序的時候才這樣設置,這將確保時鐘測試正確。

2.7 創建Expect

    目前最新版本的Expect是5.44,但是官方說5.44在重入上還有一些問題,建議使用5.43。
源代碼包可能是這樣的文件名:expect-5.43.0.tar.bz2。不過5.43也有bug,需要修復一下,
補丁文件可能是這樣的文件名:expect-5.43.0-spawn-1.patch。
    整個過程比較快,不到一分鐘就能搞定,也只需要4~5MB的磁碟空間。
    首先解壓縮源代碼,進入源代碼目錄:

    #tar -jvxf expect-5.43.0.tar.bz2
    #cd expect-5.43

打補丁,修Bug:

    #pathc -Np1 -i ../expect-5.43.0-spawn-1.patch

為了讓Expect也能夠完全獨立,還需要對它的configure文件做些修改:

    #cp configure{,.bak}
    #sed 's:/usr/local/bin:/bin:' configure.bak > configure

作準備工作:

    #./configure --prefix=/toolchain --with-tcl=/toolchina/lib \
    --with-tclinclude=/toolchain/include --with-x=no

各選項的含義是:

    --with-tcl=/toolchain/lib
    告訴configure腳本,Tcl解釋器在哪裡。這裡要用剛剛創建的Tcl,否則就會使用你系
    統的Tcl了。

    --with-tclinclude=/toolchain/include
    告訴configure腳本,Tcl的頭文件位置。

    --with-x=no
    不使用X圖形系統支持,因為沒有Tk(Tcl的圖形用戶界面組件)。
開始創建:

    #make

安裝:

    #make SCRIPTS="" install

安裝選項的含義:

    SCRIPTS=""
    這個選項防止安裝 Expect 所補充的一些並不需要的腳本。
最後作些收尾工作,回到sources目錄下。
    另外,與Tcl一樣,在安裝之前,可以測試一下:

    #make test

但是這也是不必要的,同樣在某些環境下會失敗。

2.8 創建DejaGNU

    最新版本是1.4.4。源代碼包的文件名可能是:dejagnu-1.4.4.tar.gz整個過程不到一分
鍾,需要6~7MB的磁碟空間。
    解壓縮源代碼包,進入源代碼目錄:

    #tar -zvxf dejagnu-1.4.4.tar.gz
    #cd dejagnu-1.4.4

過程很簡單,執行下列操作:

    #./configure --prefix=/toolchain
    #make install

你要測試的話,執行下面的操作:

    #make check

最後別忘了收尾工作。

2.9 第二次創建gcc

    測試工具都已經創建完畢並安裝好了,現在就要開始第二次創建gcc和binutils了。這次的創
建將使它們連接到新的glibc,這樣就與你的系統徹底脫離了。
    另外,這些測試工具會受到偽終端的影響,如果設置不正確的話,它們是拒絕工作的。為
了保證這一點,你可以執行下列命令:

    #expect ?c 「spawn ls」

如果你得到下面的結果:

    The system has no more ptys.
    Ask your system administrator to create more.

這就說明你系統的虛擬終端沒有配製好,就不要嘗試運行測試工具了,因為那沒有什麼意義。
至於如何設置虛擬終端,已經超過本文的範圍,請查看相關專業文檔。
    閑話不多說,首先應該創建gcc,畢竟這是一個編譯器集,讓它先工作起來似乎比較讓人感
到寬心。但這時候要注意的是,這次創建的gcc是獨立於任何系統的,那麼首先就要讓它規矩的
一點,不要與任何系統有什麼絲毫牽連。這裡有一個惹禍的根苗——fixincludes腳本。在gcc的編
譯過程會運行fixincludes腳本來掃描系統頭文件目錄,並找出需要修正的頭文件,然後把修正後
的頭文件放到gcc專屬頭文件目錄里。另外,由於gcc專屬頭文件目錄會被優先搜索,結果就是
gcc使用的頭文件是你系統的頭文件,而不是你新創建的那個。這個好心辦壞事的東西,還是把
它除掉算了。通過修改gcc/Makefile.in文件來完成這個操作。將「./fixinc.sh」用「-c true」替換。簡
單的命令行操作如下:

    #cd gcc-4.2.2
    #cp ?v gcc/Makefile.in{,.orig}
    #sed 『s@\./fixinc\.sh@-c true@』 gcc/Makefile.in.orig \
    > gcc/Makefile.in

同時,第一次創建gcc時採用的是bootstrap方式,這種方式不僅僅是創建gcc,而是重複創建它幾
次。它用第一次創建生成的程序來第二次創建自己,然後又用第二次創建生成的程序來第三次
創建自己,最後比較第二次和第三次創建的結果,以確保編譯器可以毫無差錯的編譯自身。在
這種模式下,會默認帶有一個-fomit-frame-pointer編譯選項,而在關閉bootstrap模式后,這個選項
也會被取消,為了確保在關閉bootstrap模式時同樣開啟-fomit-frame-pointer編譯選項,我們需要手
工修改gcc/Makefile.in文件,在「XCFLAGS=…」的內容後面添加「-fomit-frame-pointer」,可以通
過下面簡單的指令完成操作:

    #cp ?v gcc/Makefile.in{,.orig}
    #sed 『s/^XCFLAGS=$/& -fomit-frame-pointer/』 gcc/Makefile.in.tmp \
    > gcc/Makefile.in

還有需要注意的是,這次應該讓gcc預設使用toolchain的glibc,而且默認搜索目錄也不要再有
/usr/include了,為了保證這一點,需要執行下列操作:

    #for file in $(find gcc/config -name linux64.h -o -name linux.h)
    do
    cp -uv $file{,.orig}
    sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
    -e 's@/usr@/tools@g' $file.orig > $file
    echo "
    #undef STANDARD_INCLUDE_DIR
    #define STANDARD_INCLUDE_DIR 0" >> $file
    touch $file.orig
    done

這比在創建完gcc再調整specs文件要好,這樣可以保證新的動態連接器在這次創建gcc的時候就
用上。也就是說,隨後的所有臨時程序都會連接到新的glibc上。上述這些操作是非常重要的,
為了成功完成gcc的創建,一定要執行它們。
    一切準備好好,進入正題吧。與第一次相同,還是要創建一個build目錄:

    #mkdir build
    #cd build

做準備工作,執行configure腳本:

    #../configure ?prefix=/toolchain \
    --with-local-prefix=/toolchain --enable-clocale=gnu \
    --enable-shared --enable-threads=posix \
    --enable-__cxa_atexit --enable-languages=c,c++ \
    --disable-libstdcxx-pch --disable-bootstrap

各選項的含義是:
    --enable-clocale=gnu
    這個參數確保C++庫在任何情況下都能使用正確的locale模塊。

    --enable-threads=posix
    該選項使得C++的異常處理為線程安全的。

    --enable-__cxa_atexit
    用__cxa_atexit代替atexit來登記C++對象的本地靜態和全局析構函數,這是為了完
    全符合對析構函數的處理規定。它還會影響到C++ABI,並且這使得生成的C++共享庫在
    其他的Linux發行版上也能使用。

    --enable-languages=c,c++
    同第一次一樣,此時又加入了C++編譯器的支持。

    --disable-libstdcxx-pch
    該選項使得不創建libstdc++預編譯頭(PCH),它佔用了很大的空間,而且還用不到它。

    --disable-bootstrap
    該選項關閉bootstrap模式。目前的gcc是默認開啟bootstrap模式的。
開始創建gcc:

    #make

此時可以執行gcc的測試套件了,不過肯定會有錯誤的,因為它太過全面了:

    #make ?k check

這裡的-k參數使得測試套件即使遇到錯誤也要繼續運行,直到完成。接下來執行安裝程序:

    #make install

好了,這項重要的工作完成了。可以執行2.4章所介紹的測試方法測試一下,如果執行下列命
令后:

    #readelf ?l a.out

如果可以看到類似下面的內容:
    [Requesting program interpreter:/lib/ld-linux.so.2]
這說明你的操作成功了,如果沒有,你的麻煩就大了。
    好了,你已經完成了gcc的第二次創建工作,可以繼續下面的工作了,最後別忘了收尾工
作,畢竟磁碟空間很重要啊。此次你可以將gcc的源代碼都刪掉了。

2.10 第二次創建binutils

    這次創建binutils的步驟與第一次基本一樣:

    #cd binutils-2.18
    #mkdir build
    #cd build
    #../configure ?prefix=/toolchain \
    --disable-nls ?with-lib-path=/toolchain/lib
    #make

不太相同的是在執行configure腳本時,帶有一個--with-lib-path選項。這個選項指示configure腳本
在binutils創建過程中將傳遞給連接器的庫搜索路徑設置為/toolchain/lib,也就是使用新創建的程
序庫。
    接下來測試套件可以發揮一下了:

    #make check

現在就可以安裝了:

    #make install

最後我們還要再創建一次連接器ld,以待後面使用:

    #make ?c ld clean
    #make ?c ld LIB_PATH=/usr/lib:/lib
    #cp ?v ld/ld-new /toolchain/bin

至於這些操作的含義在第一次創建binutils時已經說明了,不再複述。不要忘了收尾工作,這次
你可以將binutils的源代碼目錄一同刪除了。

2.11 錦上添花

    到了這個階段,你的toolchain製作算是告一個段落了。由於前面說過,glibc是自包含
的,在這裡也不需要再次創建它了。所有的工具都與你的系統脫離了關係,編譯器、連接器
和程序庫它們之間也交織起來可以很好的完成本職工作了,而且你還有了功能強大的測試套
件支持工具。
    雖然這樣看起來不錯,但是你的toolchain還不能脫離你現有的系統獨立工作,除非你非
常厲害,不過我想不出這個世界上是否真的有這樣厲害的人。為什麼呢?首先,一個用C寫成
的完整程序,很少只有一個源代碼文件。它提供的所有文件都要編譯一遍,還要將它們產生的
目標文件再用連接器一一將它們與程序庫組合成最終的程序。我描述這些步驟就已經很複雜了,
你要是手工這麼操作將會是什麼結果?其次,好多源代碼包提供不止一個工具,這些工具大多
數情況下會互相依賴,有時還要依賴已安裝的軟體包,這些依賴關係都需要你來維護,如果只
有一兩個還好說,如果上千個呢?往往這個數量比你想象的還要多。另外,Linux的大多數軟
件的源代碼都提供了很好的可移植性,它們們可以運行於所有類Unix系統之上。雖然都屬於類
Unix系統,但不同的產品有不同的特性,好多軟體需要依賴這些特性。這往往需要利用預編譯
器幫忙決定採用那些特性適合何種系統。如果這些內容通過手工解決的話,工作量很可能是一
個天文數字。由此可見,你現在的這個toolchain創建一個完整的軟體系統沒有任何問題,但是
需要付出根本無法估量的冗繁的操作步驟才能完成某個簡單的軟體包的創建過程。
    懶惰是人類文明進步與發展的原動力。Unix世界的程序員經過幾十年的不懈努力,艱苦卓
絕,前仆後繼,發明並創造了一個又一個神奇而強大的工具,讓他們自己、你、我和其他所有
人都因此而受益非淺。這其中就包括gcc、binutils和glibc,還有後面我將介紹給你的所有用
於這個toolchain的工具。
    我首先要介紹給你的一個非常重要的工具——Make,它對於toolchain無比重要,畢竟你不
想一個文件一個文件的編譯各種軟體包。無論是在何種環境下make都是一個非常重要的軟體創
建工具。不管是自己進行項目開發還是安裝應用軟體,你都經常要用到make或make install。
利用make工具,你可以將大型的開發項目分解成為多個更易於管理的模塊,對於一個包括幾百
個源文件的應用程序,使用make和makefile工具就可以簡潔明快地理順各個源文件之間紛繁複
雜的相互關係。而且如此多的源文件,如果每次都要鍵入gcc命令進行編譯的話,那對程序員來
說簡直就是一場災難。而make工具則可以根據Makefile描述的規則自動完成編譯工作,並且可
以只對程序員在上次編譯后修改過的部分進行編譯。因此,有效的利用make和makefile工具可
以大大提高項目開發的效率。同時掌握make和makefile之後,你也不會再面對著Linux下的應用
軟體手足無措了。至於它們的詳細內容已經超過本文的範圍,感興趣的讀者可以參考有關專業
文檔。
    另外一個與創建軟體包有關的工具是configure腳本。Linux上的軟體大多是可以運行在其
他類Unix系統上的,而且它們之間或多或少的存在一些差異,這些差異對程序員是不透明的,
比如有的平台編譯器文件名為cc,而有的可能是gcc,還有可能是其他別的什麼。而且,即便
是在Linux上,不同的發行版本也可能存在一些差異,比如有些支持framebuffer,而有些可能
不支持。應用軟體的作者為了使他們的軟體儘可能的在大多數系統下都可以很好的工作,他們
要針對不同的環境作不同的處理,這些對於作者是沒有問題的,可是將這些代碼交付給用戶,
讓用戶決定該如何取捨卻是不可行的事情。因此,configure這個腳本工具就誕生了,它來檢
測各系統間的差異性,然後修改相應的Makefile文件,決定做如何取捨。configure腳本是由
軟體作者自己維護的,它清楚的知道在什麼樣的環境下,採用什麼樣的編譯器、編譯選項等內
容,而用戶只需要執行一下這個腳本,就一切OK了。configure是完全使用shell腳本編寫的,
幾乎可以在所有類Unix系統中運行,這就保證了它的通用性。隨著configure的發展,逐漸的擴
展了原有的功能,開始承擔軟體包的配置工作了,可以決定軟體包的那些組件被創建,那些可
以不用創建等。而且人們還發明了用於產生configure的工具,使得原來很複雜的工作變得越
來越簡單了。
    前面介紹了Make工具和confiugre腳本。這兩個重要的工具是你在創建Linux所有軟體包必
不可少的工具,你永遠也離不開它們,就像你離不開gcc、binutils和glibc一樣,否則你就無
法進行MagicLinux的開發。使用Make需要configure改寫Makefile文件,使用configure需要
shell來執行,shell來執行configure還需要更多的軟體包來支持,它們是Ncurses、Bash、
Bzip2、Coreutils、Diffutils、Findutils、Gawk、Gettext、Grep、Gzip、Make、Patch、
Perl、Sed、Tar、Util-linux。除了Ncurses之外,其他的都是按照文件名排列的,因為它們
之間不存在太多必要的依賴關係。
    Ncurses是最早的System V Release 4.0 (SVr4)中 CURSES的一個克隆。這是一個可自由
配置的庫,完全兼容舊版本的curses。簡而言之,它是一個管理應用程序在字元終端顯示的函
數庫。ncurses不僅僅封裝了底層終端功能,而且提供了一個相當穩固的工作框架
(Framework),可以在字元模式下產生美觀的界面。它提供了一些創建窗口的函數。而它的姊
妹庫 Menu、Panel和Form則對curses基礎庫及進行了擴展。這些擴展庫通常都隨同curses一起
發行。可以建立一個同時包含多個窗口(multiple windows)、菜單(menus)、面板
(panels)和表單(forms)的應用程序。窗口可以被獨立管理,例如讓它滾動或者隱藏。
Linux系統下被廣泛應用的shell——Bash就要依賴它完成字元界面的顯示功能。
    Bash是Bourne-Again Shell的縮寫,這個 Shell 是 Bourne Shell 的增強版本,也是基
准於 GNU 的架構下發展出來的。第一個流行的 shell 是由 Steven Bourne 發展出來的,為了
紀念他所以就稱為 Bourne shell,或直接簡稱為 sh。而後來另一個廣為流傳的 shell 是由柏
克萊大學的 Bill Joy設計依附於BSD版的Unix系統中的shell,這個shell的語法有點類似C語言,
所以才得名為C shell,簡稱為csh。由於在學術界 Sun 主機勢力相當的龐大,而 Sun 主要是
BSD的分支之一,所以C shell也是另一個很重要而且流傳很廣的 shell 之一。Bash是GNU計劃
中重要的工具軟體之一,目前也是 GNU操作系統中標準的shell,他主要相容於sh。所以,可
想而知的,目前幾乎所有的Linux發布都是使用bash作為管理核心的主要shell。如果沒有
shell,configure腳本是無法執行的,也就無法創建各種軟體包了。
    Bzip2是塊排序文件壓縮器,使用Burrows-Wheeler塊排列文本壓縮演算法和霍夫曼編碼來
壓縮文件。壓縮比要大於gzip工具使用的基於LZ77/LZ78的壓縮演算法(如gzip格式),接近PPM統
計壓縮演算法族的壓縮比。Linux的大部分軟體的源代碼包的文件名有.bz2,這就表明它使用了
bzip2進行的打包壓縮,需要bzip2來解壓縮。
    Coreutils如其名稱一樣,是一個核心工具包。包含如:cp、ls、mkdir、cat等常用的
shell命令。為了使你的toolchain在各種環境下都可以獨立工作,你需要它擁有這些常用命令。
    Diffutils這個軟體包里的程序向你顯示兩個文件或目錄的差異,常用來生成軟體的補丁。
它包括cmp、diff、diff3和sdiff,這些工具在很多時候很有用處,你的toolchain應該擁有它們。
    Findutils軟體包包含查找文件的工具,既能即時查找(遞歸的搜索目錄,並可以顯示、
創建和維護文件),也能在資料庫里查找(通常比遞歸查找快但是在資料庫沒有及時更新的情況
下,結果並不可靠)。configure腳本在做一些系統檢測時會用到,所以你的toolchain一定要
包含這個軟體包。
    Gawk是GNU所做的awk,Gawk 最初在1986年完成,之後不斷地被改進、更新。Gawk包含
awk的所有功能。awk是一個程序設計語言,有很強的數據處理能力。對於文本文件里的內容做
修改、比對、抽取等處理時,awk能夠以很短的程序輕易完成。如果使用C或Pascal等語言寫程
序來完成上述的動作,不但不方便還需要花費大量時間,所寫的程序也會很大。awk能夠依照
使用者定義的格式來分解輸入的數據,也可依照使用者定義的格式來輸出數據。至於awk的語
法等內容的說明已經超出本文的範圍,請讀者閱讀專業著作。
    Gettext是實現程序國際化和本地化的一種工具。最初,在美國,程序通常都採用英語
編寫,界面和文檔都用英文表述。這是很自然的事情,因為他們日常使用的就是英語。如果
這些程序只被習慣使用英語的人使用,這本身也是很正常的事,不需要有什麼改變。然而,
慢慢地,事情有了一些變化,許多的程序,不僅需要被習慣說英語的人使用,也需要被其他語
種的人使用,比如中文,日文,德文等。這些不使用英語作為母語的人,他們更希望程序的界
面或文檔,能夠以他們自己更加熟悉的語言表示。那麼,有沒有一種方法呢?這種方法可以讓
程序支持多種語言,而且可以很方便地切換語言環境,由一種語言轉換到另一種語言。正是基
於這種目的,翻譯項目試圖研究出可行的工作方案,解決這個問題,讓人們有機會開發出真正
的多語言程序。gettext是翻譯項目的重要一步,它提供了一個工作框架,由一些集成的工具
和文檔組成,幫助程序員、翻譯人員和最終用戶實現程序的國際化和本地化。需要說明的是,
gettext只是實現此目標的一種方法,還有其他方法的存在。如果你的toolchain要支持多語言,
gettext是非常明智的選擇。
    Grep(global search regular expression(RE) and print out the line,全面搜索正
則表達式並把行列印出來)是一種強大的文本搜索工具,它能使用正則表達式搜索文本,並把
匹配的行列印出來。Unix的grep家族包括grep、egrep和fgrep。egrep和fgrep的命令只跟grep
有很小不同。egrep是grep的擴展,支持更多的re元字元, fgrep就是fixed grep或fast grep,
它們把所有的字母都看作單詞,也就是說,正則表達式中的元字元表示回其自身的字面意義,
不再特殊。linux使用GNU版本的grep。它功能更強,可以通過-G、-E、-F命令行選項來使用
egrep和fgrep的功能。Shell腳本在缺少grep支持的時候,幾乎寸步難行。
    Gzip是GNU zip的縮寫,它是一個 GNU 自由軟體的文件壓縮程序。gzip 的基礎是
DEFLATE,DEFLATE 是 LZ77 與哈夫曼編碼的一個組合體。文件名以.gz結尾的源代碼包就是采
用Gzip壓縮和解壓的。
    Make就不用多說了,前面已經有很詳細的介紹了,沒有它你將寸步難行。
    Patch是前面介紹的Diffutils軟體包中diff程序的一個介面。diff有很多選項,但是該
命令最常用的用途是用來生成一個文件,該文件中列出了內容發生改變的行,顯示兩個原始文
件修改過的行以及由於內容沒有變化而忽略掉的行。patch典型地用於把一個目錄下的源代碼
文件更新到新的版本,從而就避免了下載整個新的源代碼檔案的必要。下載一個有效的patch
僅僅需要下載發生變化的那些代碼行就可以了,這往往是由diff產生的。patch最初源自十幾
年前,那時網路帶寬的限制促進了patch的發展,然而和當時的很多Unix工具一樣,直到現在,
patch還在廣泛應用。我想你的toolchain沒有理由不包含這個工具吧。
    Perl當初只是 Unix 系統管理員的一個工具,被用在無數的小任務中。從那以後,它逐
步發展成為一種全功能的程序設計語言,特別是在各種計算平台上,它被用作 Web 編程、數
據庫處理、XML處理以及系統管理 —— 它能夠完成所有這些工作,同時仍然是處理小的日常
工作的完美工具,這是它的設計初衷。Perl 快速、有趣,而且特別有用。很多人因為需要
Perl而使用它,又因為熱愛它而繼續使用它。這樣的東西為什麼不放在你的toolchain裡面呢?
有關Perl的語法等內容超過了本文的範圍,請讀者參考其他專業著作。
    Sed (Stream EDitor)是類UNIX系統上提供將編輯工作自動化的編輯器,使用者無需直接
編輯數據。使用者可利用sed所提供的20多種不同的參數,組合它們完成不同的編輯動作。此
外,由於sed都以行為單位編輯數據,它也是一種行編輯器。一般sed最常用在編輯那些需要不
斷重複某些編輯動作的文件上,列入將文件中的某個字元串替換成另外一個字元串等。這些
相對於其他的編輯器(如:vi、emacs等)用手動的方式修改文件,sed用起來較為省力。前
面的內容,有關修改文件內容的操作,我使用的都是sed。
    Tar可以為文件和目錄創建檔案。利用tar,用戶可以為某一特定文件創建檔案
(備份文件),也可以在檔案中改變文件,或者向檔案中加入新的文件。tar最初被用來在磁
帶上創建檔案,現在,用戶可以在任何設備上創建檔案,如磁碟。利用tar命令,可以把一大
堆的文件和目錄全部打包成一個文件,這對於備份文件或將幾個文件組合成為一個文件以便於
網路傳輸是非常有用的。利用tar命令,可以把一大堆的文件和目錄全部打包成一個文件,這
對於備份文件或將幾個文件組合成為一個文件以便於網路傳輸是非常有用的。Tar還可以與
bzip2和gzip相結合,創建壓縮包,Linux上的大部分軟體源代碼是用Tar也bzip2或gzip相結合
產生的壓縮包形式發布的。Tar產生的文件包文件名以.tar結尾,與bzip2結合產生的包以
.tar.bz2結尾,與gzip結合產生的文件包以.tar.gz結尾。
    Util-linux軟體包包含許多工具。其中比較重要的是載入、卸載、格式化、分區和管理
硬碟驅動器。你的toolchain需要磁碟掛接和卸載工具,因為在創建基本Linux系統時需要掛接
proc等文件系統。
    好了,你需要的大部分軟體都介紹完了,最新版本可以在網路上獲得,我就不一一列舉了。
如果你覺得你的toolchain還需要更多更強的功能,沒問題的,下載相應的軟體包,創建安裝
就行了。當你的toolchain被眾多好用強大的軟體工具充實之後,可以做的事情不僅僅是為了
創建基本的MagicLinux系統,至於你能將它應用在何種領域或目的,就由讀者你細心體會去吧。

2.12 結束語

    感謝你能夠為了MagicLinux而來閱讀這麼生澀的文章。本章前部分詳細講述了如何創建一個
gcc環境,因為這非常重要,我不希望你在這個環節有任何失誤。
    Toolchain技術不僅僅在製作Linux發布時起到很大作用。而且在諸如嵌入式開發等那些需要
交叉環境下應用非常廣泛。本章所討論的內容也不僅限於用於MagicLinux開發的toolchain的製作,
同樣適用於其他方面應用的toolchain的製作,不過是給定的一些編譯選項有些變化。如果讀者
對這方面感興趣的話,可以據此而舉一反三,獨立思考一下,並通過互聯網尋找你要了解的問
題的答案。如果你想很快的擁有一個toolchain,而完全自己做感覺吃力的話,你可以參考LFS,
它的官方網站是http://www.linuxfromscratch.org/,那裡介紹的內容比文本要全面,而且更為
專業,本文的大部分內容也是參考它的。
    下一章我將讓你了解Linux的結構,讓你對Linux有一個徹底的了解。


Magic Linux開發入門指南(三)    一旦你擁有了一個toolchain,就擁有了製作MagicLinux的初級武器了。這個時候你可能已經開始輅
胳膊挽袖子,準備大幹一場了,可你卻突然發現,還是什麼也做不了,原因就在於你還不了解如何使
用toolchain來製作MagicLinux。下一章我將講述Linux的組織結構,讓你對Linux有一個徹底的了解,為正
式開始製作MagicLinux作準備。

第二章 Linux的文件組織結構

    像Linux這些類Unix操作系統與你所熟知的Windows有很大的不同,其中一個顯著的不同就是類Unix
操作系統的文件管理方式,它只有一個文件樹,以一個樹根「/」為起點,所有的文件和外部設備都以
文件的形式掛接在這個文件樹上,包括硬碟、軟碟機、光碟機、數據機等,而且有著非常嚴格的組織
結構。不同的Unix分支在文件組織細節方面會有一些不同,但基本層次與本文下面將介紹的內容是相
一致的。
    在Linux操作系統下,眾多軟體都被安裝在既定的位置,它們的文件名、文件內容、目錄結構等都
是固定的,相互合作的軟體系統通過這些既定的規則就可以恰當的找到它們的合作夥伴,互相配合完
成一些更為複雜的任務。作為用戶也可以在通過查看既定的位置的內容來判斷是否安裝了自己需要的
軟體,或者修改軟體的配置等,且同等的操作在任何同類系統中都能得到相同的結果。為了實現這些
目的,Linux必須嚴格的組織文件層次關係,且形成一種規範行為,才不至於因為混亂而使得用戶以及
軟體系統對操作系統產生恐慌。這充分體現了Unix的傳統——簡單。
    Magic Linux作為一個成熟的Linux發布,必定要因襲傳統標準,作為Magic Linux的開發者,熟識
Linux的文件組織結構也很自然的成為你必修的基本功課,因為這決定了你製作出來的系統能否被其他
人所接受,以及能否正確運行那些成熟穩定且應用廣泛的軟體產品。

2.1 基本組織原則

    類Unix系統的文件組織結構是按照一個基本組織原則而設計的。當你能夠深入理解這些原則之後,
你會發現目前這種組織結構是必然的選擇,你也不必牢記那些結構性的問題,而不由自主的做出與現
今沿襲下來的基本一致的布局來。
    按照各文件在系統中所起的作用,可以劃分為是否共享與是否可變兩類屬性。一般來說,不一定
需要本地系統提供的文件都可以看作為共享的,而那些必須由本地系統提供的文件則可以看作為非共
享的;能夠被保存在只讀存儲設備上的文件都可以被認為是不可變的,反之那些必須要存在可讀寫存
儲設備上的文件就是可變的。
    從是否可共享這一屬性上可以充分體現類Unix操作系統極強的靈活性與可擴展性。由於採用單一
文件樹形式,任何設備都能夠以文件方式掛接到樹的某一枝上,這使得非本地存儲設備通過某種網路
協議掛接到本地文件樹上成為可能。這樣,很有可能你正在使用的某些程序根本就不在你的計算機里,
而是在離你非常遙遠的大洋彼岸。給文件賦予是否可共享這一屬性,使得這種操作變得輕鬆且合理,
只要按照這個原則來組織文件布局,就可以很容易的提供這種讓你難以置信的強大功能。其實這也是
歷史原因造成的,畢竟在很早以前,大量的本地存儲是非常奢侈的事情,讓遠端的一個設備來存儲大
家共用的一些程序是很棒的解決方案。那些程序自然的就是為大家所共享的。然而這種共享不能解決
所有問題,畢竟本機的設備不能完全與別人的設備相同,那麼它們對應的文件也不能提供給別人使用,
自然的也就是非共享文件了。
    可變屬性在某種意義上為類Unix系統提供了很大的伸縮性,可以容易的將它們一直到很多非通用
設備上,比如電視機頂盒。它允許你合理的將那些固定不變的二進位代碼存儲在只讀設備上,而那些
隨著系統運行而時刻變化的內容,如系統日誌等可以存儲在隨機讀寫設備上,這樣便於你最大限度的
節省硬體設備上的成本開銷。於此,系統的安全性也得到了保障,畢竟很少有人希望他們那些常用的
程序可以很容易的被一些惡意程序所修改,這點Windows上的用戶們是感同身受的。
    以前,類Unix系統的文件組織結構不是非常清晰,/usr和/etc目錄混合著大量的可變與不可變的文
件。由此,引入了/var目錄,將/usr目錄下的可變文件全部轉移至/var目錄下,這就保證了/usr目錄可以
單獨放在其他設備上且以只讀方式被掛接在樹根上。目前/etc目錄下的可變文件還沒有完全轉移至/var
目錄下,但是從技術角度看,這也只是一個時間問題。
    下表列出了依照這一基本原則組織文件的典型例子:
可共享
不可共享

不可變
/usr /etc
/opt /boot
可變
/var/mail /var/run
/var/spool/news /var/lock


           
   
   
         
     
      
   
                              表2-1


2.2 根文件系統

    根文件系統保存在根分區,它擔負著系統啟動、修復、更新、恢復等重要任務。當你啟動系統成
功后,可以執行下列命令查看樹根的內容:

    #cd /
    #ls

結果可能是下面的內容:
bin   dev  lib  media  opt   root   sys   tmp   usr

boot  etc  home mnt    proc  sbin   srv   var


           
   

雖然他們井然有序的排列在一起,但是他們並不一定完全存放在同一個設備上,比如/usr、/var等,而
且/sys和/proc根本不在任何外部存儲設備上,而是在內存中。
    這裡,將直接掛接在樹根「/」上的設備叫做根設備,可能是內存,也可能是磁碟,如果是磁碟的
某一分區,就稱之為根分區,它是操作系統啟動時默認掛接的設備,是所有文件系統的根源。可謂有
了根文件系統就有了一切。如果當系統崩潰到連根文件系統都無法掛接時,你只有唯一的選擇——重
裝。
    為了啟動系統,根分區的內容必須能夠支持到系統掛接了其他設備和其它磁碟分區之後。這就要
求它必須包含必要的工具(如init、mount等),配置信息(如inittab、fstab等)以及其他重要的啟動數
據。還應該包含引導器的配置信息,但與具體引導器的不同而不同,有的需要有的可以放在其他地方。
    為了更新或修復系統,根文件系統還包含那些能夠提供這些功能的工具。保證有經驗的系統管理
員能夠重建被毀壞的部分。
    為了恢復系統,根文件系統要提供備份和還原工具,在必要的時候可以通過以前的備份恢復系統
的運行。這些備份往往保存在光碟、磁帶等大容量外存上面。
    根文件系統上的內容需要平衡考慮,要仔細斟酌將哪些內容放入根分區,盡量保證根分區的精巧。
有很多因素要求跟分區要盡量的精巧:第一,根文件系統包含了眾多的系統特有的配置文件,如:內
核、hostname文件等,這些都是系統特有的,這就意味著根文件系統不能通過網路系統共享。保證網
絡系統根分區在伺服器的最小化,可以最小化非共享文件區域 的磁碟空間浪費。這也使得工作站可
以使用更小容量的硬碟。第二,雖然你劃分了較大的根分區給根文件系統,且對它付諸了你的心血,
可是有人卻使用了更小的根分區,導致你的發布無法安裝。當系統有了更多的安裝文件,你可能會發
現這與其它使用更小根分區的系統不兼容了。作為開發者,你就把這個問題轉移給你的廣大用戶了。
第三,由於磁碟錯誤毀壞了根分區數據是致命的,更小的根分區可以盡量減小這種致命問題的發生。
應用程序不得創建或依賴根文件系統上的特定文件或子目錄,後面將要講述的其他位置可以為任何軟
件包提供更多的靈活性。這有很多原因,最主要的,從性能或安全等多方面考量,系統管理員需要保
證根文件系統精小,而且也規避了因交叉掛接而引發的各種混亂問題。
    根文件系統必須包含下列目錄,某些可以是符號連接:
名稱
功能
bin
重要的可執行文件,shell命令
boot 引導器配置文件,內核等。
dev 設備文件
etc 系統專有配置文件
lib 重要的共享庫和內核模塊
media 可移動設備掛接點
mnt 其他文件系統的臨時掛接點
opt 附加應用軟體包
sbin 重要的系統可執行文件
srv 本系統提供的用於伺服器的數據
tmp 臨時文件
usr 文件系統的第二層
var 可變數據

           
   
   
     
   
   
   
     
   
           
   
   
     
   
   
   
   
   
     
   
           
   
  
                      表2-2-1


這些內容可能與你理解的不太一樣,但這就是全部必須的內容,各目錄的詳細內容下面會逐一介紹。
而下表所列的可能就是你疑問的了,但這些是可選的,只要在有相應子系統的時候才需要。不過對於
大多數通用系統它們都是需要的。
名稱
功能

home
用戶自己的目錄

lib
其他各式的重要共享庫,比較少見

root
root用戶的專有目錄

           
   
   
     

   
   
     
   
   
                      表2-2-2


它們的具體內容也會在下面內容進行詳細介紹。

2.3 子目錄
    本節將講述根文件系統下各子目的詳細內容,以及為了使系統能夠運行它們所必須包含的內容。
/usr和/var由於本身的複雜性,我會以單獨的章節介紹它們。

2.3.1 /bin

    /bin目錄下包含了用戶命令文件,也就是shell命令,供所有用戶使用。不僅僅是用戶,腳本程序也
要使用它們。即使其他文件系統還沒有被掛接時,它們也要能夠工作。
    /bin目錄不得包含任何子目錄,下表列出了它必有的內容,有些文件可能是一個符號連接:
名稱 功能
cat 連接多個文件,並將內容輸出至標準輸出
chgrp 改變文件的所屬組
chmod 改變文件的訪問許可權
chown 改變文件的所屬用戶和組
cp 複製文件和目錄
date 列印或設置系統日期與時間
dd 轉換並複製文件
df 查看文件系統磁碟空間使用情況
dmesg 列印或控制內核的消息緩衝
echo 顯示一行文本
false 不做任何事情,表示不成功
hostname 顯示或設置系統的主機名
kill 向進程發送信號
ln 創建文件連接
login 開始系統上的一個會話
ls 列出目錄內容
mkdir 創建目錄
mknod 創建塊或字元設備的專用文件
more 分頁顯示文本
mount 掛接一個文件系統
mv 移動文件或更改文件名
ps 查看系統進程狀態
pwd 列印當前工作目錄名
rm 刪除文件或目錄
rmdir 刪除空目錄
sed 一個流式文本編輯器
sh Bourne命令shell
stty 改變或列印終端行設置
su 改變用戶標識
sync 刷新文件系統緩存
true 什麼也不做,表示成功
umount 卸載文件系統
uname 列印系統信息

           
                                  表2-3-1


如果/bin/sh不是真正的Bourne shell,它必須連接到一個真正的shell命令上,既可以是硬連接也可以是軟
連接。例如,調用sh或bash時,bash會有不同的行為。使用符號連接也使得用戶容易地了解到/bin/sh不
是一個真正的Bourne shell。「[」和「test」命令必須被放在一起,既可以在/bin目錄下也可以在/usr/bin
目錄下。這是為了保持與POSIX.2標準一致,即使它們已經由shell程序內部實現了。

    下表的內容是可選的。如果有相應的子系統被安裝,則是必須的。目前大多數發布都會部分的提
供它們。
名稱 功能
csh 著名的C shell
ed 「ed」文本編輯器
tar tar打包工具
cpio cpio打包工具
gzip GNU壓縮工具
gunzip GNU解壓縮工具
zcat GNU解壓縮工具
netstat 網路統計工具
ping ICMP網路測試工具
   
   
     
   
   
   
     
   
           
   
   
     
   

  
           
                           表2-3-2


如果存在gunzip和zcat程序,它們一定是gzip的軟連接或硬連接。/bin/csh可能是/bin/tcsh或/usr/bin/tcsh的符
號連接。tar、gzip和cpio為系統提供了恢復能力,反之,如果不考慮從根分區恢復系統的話,這些程序
可被忽略(例如一個只讀片內根系統,通過NFS掛接/usr目錄)。若要通過網路恢復系統,還需要ftp或
tftp存在於根分區。

2.3.2 /boot

    該目錄包含了除在啟動時刻和映像安裝器不需要的配置文件外,啟動進程所需要的所有內容。換
句話說,/boot目錄下存儲的數據用於內核開始執行用戶級程序之前的操作。這裡也可能包含備份的主
引導扇區信息和扇區映像文件。另外,操作系統的內核必須放在「/」或「/boot」目錄下。

2.3.3 /dev

    /dev目錄是設備文件或專有文件的存放位置。要是/dev中的設備需要手工創建,/dev必須含有一個
名為MAKEDEV的命令,它能夠創建需要的設備文件。同時也應該為任何本地設備包含一個
MAKEDEV.local文件。如果需要,MAKEDEV必須具備為任何發現與系統的設備創建文件的許可權,而
不限於那些特定的安裝實現。

2.3.4 /etc

    /etc包含了系統特有的配置文件。所謂配置文件,就是用於控制程序運行的本地文件,它一定是
不可變文件,而且是可編輯的,那些二進位可執行文件是不能作為配置文件的。/etc下基本沒有二進
制文件,下表中列出的目錄需要包含在/etc下,有些可能是符號連接。
名稱 功能
opt /opt目錄下各軟體的配置文件
X11 X Window系統的配置文件,可選。
sgml SGML的配置文件,可選。
xml XML的配置文件,可選。

   
   
     
   
  
       
   
                         表2-3-3

當相關子系統安裝后,下列文件必須放在/etc中,有些也可以是符號連接:
名稱 功能
csh.login C shell登陸的全局初始化文件,有C shell時有效。
exports NFS文件系統的訪問控制列表,有NFS支持時有效。
fstab 文件系統的靜態信息,系統初始化時需要掛接多個文件系統時需要。
ftpusers FTP守護進程的用戶訪問控制列表。
geteways routed的網關列表。
gettydefs getty程序的配置文件。
group 用戶組列表文件。
host.conf 決定如何解析域名。
hosts 主機名靜態信息。
hosts.allow 允許訪問本機的IP地址列表。
hosts.deny 禁止訪問本機的IP地址列表。衝突時,優先。
hosts.equiv 信任主機列表,作用於rlogin,rsh,rcp。
hosts.lpd 信任主機列表,作用於lpd。
inetd.conf inetd守護進程的配置文件。
inittab init程序的配置文件。
issue 登陸提示符上面的消息和標識文件。
ld.so.conf 搜索共享庫的目錄列表文件。
motd 本機的標識信息,遠程登陸時確認你當前控制的是本機還是遠程計算機。
mtab 文件系統的動態信息,記錄當前掛載的文件系統。
mtools.conf mtools程序的配置文件。
networks 網路名稱的靜態信息,與hosts類似。
passwd 用戶密碼文件。
printcap ldp印表機的性能資料庫。
profile sh shell登陸的全局初始化文件。
protocols 網路協議定義文件。
resolv.conf DNS域名解析的配置文件。
rpc RPC協議定義文件。
securetty Root登陸的TTY訪問控制文件。
services 記錄網路服務名和它們對應使用的埠號及協議。
shells 可使用的登陸shell路徑名。
syslog.conf syslogd守護進程的配置文件。

表2-3-4     
   
這裡,顯然mtab就不適合/etc內單純為不可變文件的原則,這在今後會逐步得到解決。
(未完...待續...)



Magic Linux開發入門指南(四)    /etc/opt目錄下的內容是為/opt而準備的。附加應用軟體包的配置文件必須安裝在
/etc/opt/下,其中的與/opt下的對應軟體包目錄相同。

    /etc/X11目錄下的內容是X Windows系統的配置文件,X Windows系統的所有主機
相關配置文件全都在這裡。這使得在/usr以只讀方式掛接時,可以局部控制
X Windows系統。只要安裝了X Windows系統,下表中的文件必須安裝在/etc/X11目錄
下:
名稱 功能
Xconfig XFree86早期版本的配置文件。
XF86Config XFree86第3、4版的配置文件。
Xmodmap 定義xdm和xinit所要使用的鍵盤映射。
xorg.conf Xorg的配置文件。

   
   
   
   
   
   
   
                                                 表2-3-5


/etc/X11下的那些子目錄是為xdm以及別的程序(如窗口管理器)準備的。那些只有
一個配置文件的窗口管理使用的配置文件名是system.*wmrc(除非有約定俗成的名
字),一般不佔用一個子目錄。任何窗口管理器的子目錄一定與它實際的可執行文
件名相一致。

    /etc/sgml和/etc/xml里的內容是SGML和XML的配置文件,這是可選的。定義它們
高級參數的基本配置文件就安裝在這裡。


2.3.5 /home
    /home為用戶專有目錄,每個用戶都會在/home目錄下有其對應的子目錄,而且這
個子目錄一般與他的用戶名相同。沒有任何程序會依賴於這個目錄。
    同一個程序,不用的用戶有不同的配置方式,這些用戶獨有的配置文件就保存
在他的home目錄中,一般以「.」開頭(即隱藏文件)。如果某個程序需要創建多個
配置文件,它就會在用戶的home目錄下創建一個以「.」開頭的目錄(即隱藏目
錄),將這些配置文件放入目錄中。這種情況下,配置文件不再需要以「.」開頭
了。

2.3.6 /lib
    /lib目錄里存放著必備的共享庫和內核模塊。在系統啟動和運行根文件系統上的
各種命令時,都要用到這些共享庫。必須至少存在一組下列文件名組合方式的一組
文件(可以是文件,也可以是符號連接):
文件名組合 功能
libc.so.* C動態鏈接庫。
ld* 運行時連接器/載入器。

   
   
        
                          表2-3-6


如果安裝了某個C預處理器,由於歷史原因,/lib/cpp必須是它的連接。modules子目錄
必須存在於/lib目錄下,它是內核可裝載模塊的存放位置。

2.3.7 /lib
    有些時候,系統為了支持不只一種可執行文件格式,會需要有多個不同的/lib目
錄來單獨保存必須的共享庫。一般的,在處理這個問題時會在lib後面追加一些修
飾,如AMD64系統的/lib64等。這種情況下就不再需要/lib/cpp了。
    象PPC64、s390x、sparc65和AMD64這些即支持64位程序也支持32位程序的平台
下,/lib得到了充分的發揮。在這些平台下,必須將所有64位庫放置在/lib64
中,而32位庫則依然放置在/lib中,這保證了對原有32位程序的平滑兼容。完全64位
架構的IA64不支持32位程序,則只有/lib,也就是說所有的64位庫都要放置在/lib中。

2.3.7 /media
    該目錄用於掛接如軟盤、光碟、U盤等可移動設備,其各子目錄掛接各種類型
設備,從其目錄名可了解具體設備類型。曾經出現過很多其他名稱的掛接點,如
/cdrom,/mnt或/mnt/cdrom等,現在統一規範到/media中。雖然很多人習慣於將這些
可移動設備掛接在/mnt子目錄中,但這與傳統不符,因為/mnt實際上只是臨時掛接
點。下表的內容一定要出現在/media目錄中,具體內容與系統實際情況有關。
名稱 功能
floppy 軟盤驅動器
cdrom CD-ROM
cdrecorder 光碟刻錄機
zip Zip磁碟驅動器,現在比較少見

   
   
   
   
   
   
        
                          表2-3-7

如果系統中有不止一個同類的驅動器,則在其掛接類型目錄名後面帶有一個0起始的
數字,比如「cdrom0、cdrom1、…..」。

2.3.8 /mnt
    提供這個目錄是讓系統管理員臨時掛接某個文件系統的。此目錄的內容屬於局
部問題,不應該影響任何程序的運行。千萬不要在這裡安裝什麼程序,畢竟一個臨
時目錄在系統不需要它的時候會被其他東西佔用。

2.3.9 /opt
    這裡是系統附加軟體包的棲息地。每個軟體包會在/opt下擁有一個自己的目錄,
那裡面存放著他所有的可執行程序和靜態數據。這個專有目錄名應該與它本身的名
字相一致,這樣用戶就很容易管理它們了。也可以使用廠商名稱,不過這個廠商名
稱必須是在Linux名稱與號碼分配管理局註冊過的,不過廠商名下面還應該是軟體
名,畢竟同一個廠商可以有多個軟體。
    /opt/bin、/opt/doc、/opt/include、/opt/info、/opt/lib和/opt/man是保留給本地系統管理
員使用的。有些軟體包可能會提供一個前端文件(連接或副本),系統管理員可以
將這個文件放在這些保留目錄中,但是在缺少這些保留目錄時也要保證可以正常工
作。
    用戶調用的程序必須放在軟體包目錄下的bin子目錄中。如果包含Unix指南頁,
則要將它們放在對應軟體包的share/man子目錄下,而且也必須擁有與/usr/share/man目
錄中相同的組織結構。
    軟體包有可變文件,必須將這些可變文件安裝在/var/opt目錄下。見/var/opt一
節,會有更詳細的介紹。
    本機專有的配置文件必須安裝在/etc/opt目錄下,見/etc一節的介紹。
    沒有哪些附加軟體包會將它們的文件放在/opt、/var/opt和/etc/opt之外,除非那個
軟體包的某些文件必須放在特定位置,否則不能正常工作。比如,設備鎖文件必須
放在/var/lock中,設備文件必須放在/dev中。
    一些Linux發行版可能在/opt目錄下安裝了軟體,在沒有徵得本地管理員同意時,
千萬不要擅自更改或刪除這裡的軟體。
    為附加軟體提供/opt目錄,是類Unix世界非常優良的傳統習慣。發布版對/opt目
錄的使用應該做些少許的限制,因為發布的軟體與本地安裝軟體可能會發生衝突,
尤其那些使用固定路徑的軟體。

2.3.10 /root
    是否為root帳戶提供專有home目錄取決於開發者或者用戶的使用習慣。不過還是
建議提供這個/root目錄。

2.3.11 /sbin
    必備的系統軟體存放處。用於系統維護的軟體和某些只限root用戶使用的命令存
儲在/sbin、/usr/sbin以及/usr/local/sbin目錄下。/sbin目錄存儲的則是那些在系統啟動、
恢復、還原以及修復過程中必備系統工具,也是對/bin下內容的補充。那些已知
在/usr被掛接之後才需要的程序一般可以放在/usr/sbin目錄下。用戶自行安裝的系統管
理程序應該放在/usr/local/sbin目錄下。下表所列的各種命令應該出現在/sbin目錄下。
名稱 功能
shutdown 關機命令
fastboot 快速從新啟動系統,不做磁碟檢測。可選。
fasthalt 快速停止系統運行,不做磁碟檢測。可選。
fdisk 磁碟分區表維護工具。
fsck 文件系統檢測與修復工具。
fsck.* 特定文件系統檢測與修復工具。
getty getty程序,設置終端機模式、連線速率和管制線路。
halt 停止系統運行。
ifconfig 網口配置工具。
init 系統初始化進程。內核調用的第一個用戶進程。
mkfs 創建文件系統,也叫格式化。
mkfs.* 創建特有的文件系統。
mkswap 格式化交換分區。
reboot 重新啟動系統。
route IP路由表維護工具。
swapon 開啟頁交換。
swapoff 關閉頁交換。
update 周期性的刷新文件系統緩衝的守護進程。

表2-3-8


2.3.12 /srv
    某些服務進程啟動之後,它們需要讀取的數據會放在/srv目錄中。提供/srv目錄
一方面為了方便用戶找到特定服務的數據文件,另一方面也為某些服務放置它們的
執行腳本(如CGI腳本)、只讀或可寫數據提供一個合適的地方。提供給特定用戶
的數據應該放在那個用戶的home目錄下。
    目前還沒有規範的/srv下子目錄的命名方法。有一種方式是按照協議構造/srv下
的數據,如ftp、rsync、www、cvs等等。對於大型系統,可能利用功能管轄範圍構
造/srv下的內容,如/srv/physics/www、/srv/compsci/cvs等。它的具體內容在不同主機間
會有很大的差異,因此,沒有程序會依賴於/srv下特定的子目錄結構,也沒有那個程
序必須在/srv下保存數據。不過,/srv目錄始終會作為服務進程數據存放地而一直存
在著。

2.3.13 /tmp
    /tmp必須能夠被任何程序、任何用戶訪問,它存放臨時文件。任何程序都不用
對/tmp目下任何文件或目錄負責,儘管如此,還是建議系統重起后,應該清除/tmp目
錄下的內容。

2.4 /usr目錄組織結構
    /usr是整個文件系統的第二個主要區段。它既是可共享的也是只讀的,這意味
著/usr可以共享於多種主機之間,但不能寫入。任何主機專有的或隨時間變化的信息
只能存放在其他地方。
    即使是大型軟體包,也不得佔用/usr下的一個獨立子目錄。下表所列的目錄或目
錄的符號連接要求出現在/usr下:
名稱 功能
bin 大部分用戶命令。
include C/C++程序頭文件目錄。
lib 程序庫。
local 用戶自行安裝的程序存放於此。
sbin 非重要的系統程序。
share 體系結構獨立數據。

表2-4-1


下表所列目錄是可選的,根據具體軟體安裝情況而定:
名稱 功能
X11R6 X Window 11 第六版
games 育教娛樂程序
lib 備用格式程序庫,如lib64。
src 源代碼。
sbin 非重要的系統程序。

表2-4-2


這裡有一個例外,就是X Windows系統,它佔有了一個獨立子目錄,這是歷史原因導
致的。
    為了與老系統保持兼容,可以在/usr目錄下創建下列符號連接:
/usr/spool —〉/var/spool
/usr/tmp —〉/var/tmp
/usr/spool/locaks —〉/var/lock

   
   
   
              表2-4-3

這是因為這些目錄早先是在/usr下的,後來轉移到了/var目錄下。一旦系統不再需要
那些符號連接了,可以直接刪除。

2.4.1 /usr/X11R6
    該目錄保留給X Window 11第六版和與其有關的文件的。為了使XFree86與其它
系統的X Window相兼容,只要有/usr/X11R6目錄就一定要有下表中的符號連接:
/usr/bin/X11 —〉/usr/X11R6/bin
/usr/lib/X11 —〉/usr/X11R6/lib/X11
/usr/include/X11 —〉/usr/X11R6/include/X11

   
   
   
   
   
                  表2-4-4

通常,不得利用這些符號連接安裝或管理軟體,它們僅供用戶使用。另外,在
X Window發布版本更替期,沒什麼好方法可以了解當前使用的是X11的那個版本。
保存在/usr/X11R6/lib/X11的主機專屬數據應解釋為示範文件。應用程序需要了解
本機信息時,必須參考/etc/X11下的某個配置文件,雖然這個配置文件可能是
/usr/X11R6/lib下某個文件的連接。

2.4.2 /usr/bin
    系統中絕大多數的可執行文件都放置在這裡。下表所列的目錄必須放在/usr/bin
下,除非沒有安裝與它們相關的系統:
名稱 功能
mh MH郵件處理系統的命名所在目錄。
/usr/bin/X11 如果存在/usr/X11R6/bin目錄,一定是它的符號連接。

   
   
   
       
                      表2-4-5


下表所列的文件或符號連接也必須放在/usr/bin目錄下,除非你沒有安裝這些軟體:
名稱 功能
perl 經典的perl語言解釋器。
python 最近非常流行的python語言解釋器
tclsh 古老而特別的tcl解釋器。
wish 圖形界面的tcl解釋器。
expect Tcl語言非常經典的擴展部分,實現程序的自動交互。

   
   
   
   
   
   
   
   
   
   
                       表2-4-6


讀者會發現一個特別的地方,我所列出來的這些程序都是某種腳本語言的解釋器或
擴展部分。這是因為shell腳本解釋器(shell腳本的第一行往往帶有一個!#類型
的註釋)不能依賴於某個具體目錄,這就要求必須標準化它們的位置。Bourn shell和
C shell解釋器已經被鎖定在/bin目錄中了,可是Perl、Python和Tcl卻經常被放置在不同
的地方,於是/usr/bin下的內容往往是到其實際位置的符號連接。

2.4.3 /usr/include
    標準頭文件存放目錄,系統內所有通用的C語言頭文件都要放置在這裡。如果
有/usr/X11R6/include/X11存在,則一定要建立/usr/include/X11這個符號連接。

2.4.4 /usr/lib
    /usr/lib內的內容是庫和目標文件,它們都是二進位文件,但不被用戶和shell腳本
直接執行。應用程序可以在這裡創建獨立的子目錄。如果應用程序在這裡創建了獨
立的子目錄,它所有的與體系結構有關的執行數據都必須放在這個子目錄中。
    由於歷史原因,如果有/usr/sbin/sendmail存在,則必須在/usr/lib下創建sendmail符號
連接;如果有/lib/X11存在,也必須在/usr/lib下創建X11的符號連接,即使/lib/X11也是
一個符號連接也要這樣做。

2.4.5 /usr/local
    /usr/local是供系統管理員安裝局域性軟體使用的,這保證了當系統更新時不會把
它們覆蓋掉。/usr/local也可被用於在一組主機之間共享程序和數據,不過不能在/usr
中也有同樣的東西。下表所列的目錄或符號連接必須出現在/usr/local中。
名稱 功能
bin 局域性可執行文件。
etc 局域性軟體的配置文件目錄。
games 局域性育教娛樂可執行文件。
include 局域性C頭文件。
lib 局域性程序庫。
man 局域性在線指南。
sbin 局域性系統管理可執行文件。
share 局域性體系結構無關數據。
src 局域性源代碼。

   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
                          表2-4-7

默認情況下不會再有其他的子目錄了。/usr/local/etc也可能符號連接到/etc/local,這更
適用於將所有配置文件放置在/etc下這一規則。

2.4.6 /usr/sbin
    那些非必要的系統管理軟體可執行文件就存放在這裡。那些用於還原、更新、
修復系統,以及掛接/usr目錄的系統管理程序都必須放置在/sbin目錄下。

2.4.7 /usr/share
    這裡存放著所有體系結構無關的數據文件,它的內容可以共享給運行在任何體
繫結構下的操作系統。例如,某個站點可能由i386、Aplpah和PPC三種體系結構平台
構成,但是它們可能共同維護唯一的一個掛接自某處的/usr/share目錄。需要注意的
是,雖然/usr/share可以共享於不同體系結構之間,但必須保證它們運行的是不同發布
平台的相同操作系統。
    任何程序或軟體包包含或需要的不需要修改的體系結構無關的數據都應該保存
在/usr/share(如果安裝的是局域性軟體,應該是/usr/local/share)目錄中。同時也建
議/usr/share下的任何子目錄也應用於此目的。保存在/usr/share/games下的遊戲數據必
須是純粹的靜態文件,類似於分值、日誌等文件,必須放置在/var/games中。
    下表所列目錄或符號連接必須出現在/usr/share中:
名稱 功能
man 在線指南。
misc 體系結構無關的其他數據。

   
   
   
  
   
                          表2-4-8


    下表所列目錄或符號連接,與你所安裝的軟體有關,如果有則必須出現
在/usr/share中:
名稱 功能
dict 單詞列表。
doc 其他文檔。
games /usr/games的靜態數據文件。
info GNU Info系統的主目錄。
locale 本地信息。
nls 本地語言支持的消息目錄。
sgml SGML數據。
terminfo terminfo資料庫目錄。
tmac 沒有與groff一同發布的troff宏。
xml XML數據。
zoneinfo 時區配置信息。

                          表2-4-9


建議將那些應用程序專有的,且體系結構無關的目錄放置在這裡,例如:groff、
perl、ghostscript、texmf等等,為了向後兼容,某些發布版也會將它們放置在/usr/lib
下,出於同樣的原因,/usr/share/games也可能會被這樣處理。

2.4.8 /usr/share/man
    本節會詳細的介紹貫穿於整個系統的在線指南的文件組織結構,當然,也會包
括/usr/share/man目錄下的組織結構。
    /usr/share/man是各種指南頁面存儲的主要目錄,它包含了「/」和「/usr」下大部
分程序的幫助信息。各指南頁面被存儲在//man
/這一
路徑中。下面將逐步解釋
    當你打開/usr/share/man目錄,你會看到如man1、man2、…、man8這樣的子目錄,
它們的具體分工如下:
    lman1:公共可用的命令或軟體的指南頁面保存在這裡。
    lman2:所有系統調用(可以理解為類似Windows的API)的說明保存在這裡。
    lman3:庫函數的說明信息保存在這裡。
    lman4:特種文件的說明保存在這裡,如/dev目錄下的設備文件和提供網路協
           議支持的內核介面等。
    lman5:大部分數據文件的格式說明保存在這裡。這包括各種包含文件、程序
           輸出文件和系統文件。
    lman6:寓教於樂程序、演示程序和一些不太重要的程序的說明文檔保存在這
           里。
    lman7:其他類型的在線幫助信息保存在這裡。如troff等文本處理宏的信息。
    lman8:系統維護程序文檔保存在這裡。當然,這些程序有時也適合普通用戶
           使用。
上述目錄也必須出現在/usr/share/man/中,除非它們裡面沒有任何內容。
這是為了提供多語言版本支持而提供的,其中就代表了不同的語言。不過非
常遺憾的是,沒有中文語言的支持。可能的名稱是en、fr、ko、ja等,詳細資
料還請參考其他文獻,這裡就不一一列舉了。如果系統只使用一種語言的話,
是可以忽略的。
    同理,如果某些內容與體系結構有關的話,如設備驅動器或底層系統管理命
令,則需要將這些內容放置在對應的目錄下。例如:ctrlaltdel(8)的內容可能被
保存為/usr/share/man//man8/i386/ctrlaltde1.8這個文件。
    /usr/local下的軟體的在線幫助信息保存在/usr/local/man中。X11R6的保存
在/usr/X11R6/man中。它們的組織結構與/usr/share/man是相同的。
    數字1至8即為前面講述的
。通常,每一個幫助頁都有一個獨立文件,
這個文件要帶有一個「.
」的後綴,如ctrlatlde1.8。另外,某些大型軟體系統
的幫助文檔可能不遵循這一規則,反倒會使用它們自己定義的後綴。如X Window就
會使用.x作為後綴。
    其他位置的幫助文檔,提供多語言版本支持時,同樣遵循/usr/share/man的多語言
版本支持規則,包括後面將要講述的/var/cache/man目錄。

2.4.9 /usr/share/misc
    那些不需要在/usr/share目錄下擁有自己目錄的應用程序,會將它們的體系結構無
關的數據放置在這裡。
    下表所列內容就是會出現在/usr/share/misc目錄下的內容:
名稱 功能
ascii ASCII碼錶。
magic file命令使用的特徵符號表。
termcap 終端性能資料庫。
termacp.db 終端性能資料庫。

   
   
   
   
   
   
   
   
                         表2-4-10


2.5 /var目錄組織結構
    /var目錄包含著系統中絕大多數的可變數據,如系統日誌、spool目錄與文件等。
/var的某些內容不能共享給其他系統,最典型的就是/var/logs、/var/lock和/var/run。
當然,某些內容是可以共享給其他系統的,特別是/var/mail、/var/cache/man和
/var/spool/news。
    /var的創建就是為了使得/usr可以只讀方式被掛接成為可能。/usr裡面的東西一旦
有被寫入的要求,則必須轉移到/var下。
    若是無法為/var分配一個單獨的分區,通常更好的選擇是將/var轉移至/usr目錄下
(這是為了節省根分區的空間,讓它盡量精小化)。不過即使這樣,也千萬不要直
接將/var連接到/usr,因為這就很難區分/var和/usr了。正確做法是將/var連接至/usr/var。
    通常情況下,應用程序不得在/var頂層添加任何目錄。這個位置只留給那些影響
到整個系統的軟體,而且還需要經過Linux社團商議之後決定是否添加。
    下表所列目錄或符號連接是/var下必須具備的內容。
名稱 功能
cache 應用程序的緩存數據。
lib 可變狀態信息。
local /usr/local的可變數據。
lock 鎖文件。
log 日誌文件與目錄。
opt /opt的可變數據。
run 與當前運行進程有關的數據。
spool spool應用程序數據。
tmp 系統重新啟動期間起到保護作用的臨時文件。

表2-5-1


下面列出的目錄都是保留的,某些新的應用程序不得擅自使用它們,否則可能造成
與歷史或局部性規則產生衝突:

    /var/backups
    /var/cron
    /var/msgs
    /var/preserve

當你的系統安裝了某些程序,則下表所列的目錄或符號連接必須放置在/var中。
名稱 功能
account 記錄進程的運行情況。
crash 系統崩潰產生的dumps。
games 寓教於樂程序的可變數據。
mail 用戶郵箱文件。
yp 網路信息服務(NIS)資料庫文件。


表2-5-2


2.5.1 /var/account
    該目錄包含了當前活動進程的運行情況日誌和複合進程的利用率數據。這些內
容用在類Unix系統的lastcomm和sa程序。

2.5.2 /var/cache
    該目錄的內容是來自應用程序的緩存數據,這些內容可以加快那些費時的運算
或I/O處理任務。應用程序必須能夠再生或恢復這些數據。與/var/spool不同,刪除緩
存文件不會造成數據丟失錯誤。
    /var/chace下的數據有一定的時效性,這取決於使用它的程序或系統管理員,有
時這兩者會同時影響這些數據的時效性。應用程序必須有能力恢復被手工刪除的緩
存數據(通常是因為磁碟空間有限,才會手工刪除緩存文件)。另外,緩存數據沒
有格式要求。
    為緩存數據單獨劃分一個目錄,就可以讓系統管理員將它們設置在其他磁碟上,
而且還可以從/var的其他目錄備份策略。這是/var/cache存在的意義所在。

2.5.3 /var/crash
    雖然這個目錄不能被Linux系統所使用(Linux不支持系統崩潰dumps),但是它可
以為其他支持這一功能類Unix系統所使用。

2.5.4 /var/games
    /usr中那些寓教於樂類程序的可變數據存放於此,而那些靜態數據,如幫助文本,
級別定義等內容,必須放在別處,最合理的就是/usr/share/games下。

2.5.5 /var/lib
    該目錄保存著那些與某個應用程序或系統有關的狀態信息。狀態信息,即程序
運行過程中不斷修改的那些數據,且僅於具體系統有關。對於控制程序的具體行為,
用戶不應該通過修改/var/lib下的文件來完成。
    在應用程序啟動期間或同一個程序不同實例之間,狀態信息通常用於保護程序
的所處的狀態的。
    一個應用程序(或一組相關聯的應用程序)必須為其狀態數據佔有/var/lib下的一
個子目錄。不過還有一個misc子目錄,專門提供給那些不需要一個子目錄的程序。
其他子目錄應僅提供給那些包含在發行版中有這一需求的應用程序。
    /var/lib下的各子目錄的命名應該被所發布的所有軟體包支持,當然,不同的發布
版可以使用不同的命名方式。

2.5.6 /var/lock
    鎖文件必須被保存在/var/lock目錄結構中。
    鎖文件用於硬體設備和其他被多個應用程序共享的資源,例如串列設備鎖文
件,最初可能放在/usr/spool/locks或/usr/spool/uucp中,現在,必須放在/var/lock中。鎖
文件的命名方式必須是「LCK..」後接設備及本名。例如,/dev/ttyS0的鎖文件名
為「LCK..ttyS0」。
    鎖文件的內容組織格式,必須是HDB UUCP鎖文件格式。HDB格式以10位元組
ASCII數字字元存儲進程ID,尾部帶有換行符。例如,進程1230,它的鎖文件將包含
11字元:空格、空格、空格、空格、空格、空格、1、2、3、0和換行符。

2.5.7 /var/log
    該目錄包含了各種日誌文件。大多數日誌文件都保存在這裡或相應的子目錄
中。下表所列的文件或符號連接應該出現在/var/log中,不過這取決於系統中安裝的
具體軟體。
名稱 功能
lastlog 每個用戶上次登陸記錄。
messages 由syslogd產生的系統消息。
wtmp 所有登陸於登出地記錄。

表2-5-3


2.5.8 /var/mailbox
    此處是用戶郵箱文件的存放處,所有郵箱文件必須以UNIX郵箱格式存儲。
mail spool必須能夠訪問/var/mailbox,而且mail spool文件取自具體用戶。此目錄移自
/var/spool/mail,就是為了能夠與幾乎所有的Unix實現相一致。這一改變,使得一個
/var/mail共享於多個主機以及多個不同的Unix實現成為可能。更為重要的是,這不
需要轉移mail spool的物理位置,不過,程序和頭文件還需要轉移到/var/mail中。

2.5.9 /var/opt
    /opt下軟體包的可變數據都應該安裝到/var/opt下對應的子目錄中去,這個子目錄
名稱應該與/opt下的子目錄名稱相一致,裡面內容的組織結構沒有特殊要求。

2.5.10 /var/run
    從系統啟動開始至當前的系統運行狀態信息就保存於此。該目錄下的文件,在
系統啟動進程執行開始,必須被清空。程序可以在/var/run下擁有一個子目錄;鼓勵
程序使用不止一個運行時文件。進程標識文件(PID文件),原來是放置在/etc中
的,現在必須放置在/var/run中。PID文件的命名規則是「<程序名>.pid」,例如:
crond的PID文件名就是crond.pid。
    PID文件的內部格式依然保持不變,必須以ASCII碼的數字字元描述進程標識
符,同時末尾帶有換行符。如,若crond的進程ID為25,則/var/run/crond.pid將包含三
個字元:1、2和換行符。
    記錄當前誰正在使用系統的utmp文件也保存在這裡。那些使用Unix-domain套接
字的系統程序,必須將它們的套接字文件放置在該目錄中。

2.5.11 /var/spool
    /var/spool中的數據就是供以後用的(可以被程序,用戶,管理員處理),一旦
被處理完畢,就會被刪除。
    下表所列的目錄或符號連接,必須放置在/var/spool,不過這取決於系統中安裝
的具體軟體。
名稱 功能
lpd 印表機spool目錄。
mqueue 郵件待發隊列。
news 新聞spool目錄。
rwho Rwhod文件。
uucp UUCP的spool目錄。

 表2-5-4
2.5.12/var/tmp
    /var/tmp目錄使得應用程序要求在系統重起期間保護臨時文件或目錄成為可能,
因此,保存在/var/tmp中的數據,比/tmp中的數據得到更多的保護。
    /var/tmp中的文件或目錄,在系統啟動時不得刪除。

2.5.13 /var/yp
    網路信息服務(NIS),著名的Sun Yellow Pages(YP),其可變數據,必須保存在
該目錄中。/var/yp是NIS(YP)的標準目錄,而且幾乎被它所獨佔。

(未完...待續......)







Magic Linux開發入門指南(五)2.6 虛擬文件系統
    前面幾節所介紹的目錄和文件,都是真真正正、實實在在的存儲在具體的外部
存儲設備上的,它們可能是在本機的硬碟、快閃記憶體、光碟中,可能保存在不只一個磁
盤分區中,也可能保存在網路中其它主機的存儲設備中的。本節所介紹的幾個文件
系統,雖然它們出現在根文件系統中,但它裡面的內容卻無法在任何外部存儲設備
中找到,因為它們都在內存中。

2.6.1 proc文件系統
    proc是一個重要虛擬文件系統,通過它裡面的一些文件,可以獲取系統狀態信
息並修改某些系統的配置信息。proc文件系統本身不佔用磁碟空間,它僅存在於內
存之中,為操作系統本身和應用程序之間的通信提供了一個安全的介面。當我們在
內核中添加了新功能或設備驅動時,經常需要得到一些系統狀態的信息,一般這樣
的功能可能需要經過一些象ioctl()這樣的系統調用來完成。系統調用介面對於一些功
能性的信息可能是適合的,因為應用程序必須將這些信息讀出后再做一定的處理。
但對於一些實時性的系統信息,例如內存的使用狀況,或者是驅動設備的統計資料
等,我們更需要一個比較簡單易用的介面來取得它們。proc文件系統就是這樣的一
個介面,我們可以簡單的用cat、strings程序來查看這些信息。例如,執行下面的命
令:

    #cat /proc/meminfo

你可能會得到如下結果:

MemTotal:        254272 kB
MemFree:        104416 kB
Buffers:           23940 kB
Cached:         103972 kB
SwapCached:          0 kB
Active:            64660 kB
Inactive:           69276 kB
HighTotal:             0 kB
HighFree:             0 kB
LowTotal:        254272 kB
LowFree:        104416 kB
SwapTotal:       522072 kB
SwapFree:       522072 kB
Dirty:               48 kB
Writeback:            0 kB
Mapped:         11708 kB
Slab:            11364 kB
CommitLimit:     649208 kB
Committed_AS:   16064 kB
PageTables:        320 kB
VmallocTotal:    770040 kB
VmallocUsed:      7916 kB
VmallocChunk:   760564 kB
HugePages_Total:      0
HugePages_Free:       0
Hugepagesize:      4096 kB

同樣的,free、df、top、ps等程序的功能實現,強烈依賴於proc文件系統,為了使用
那些程序,一定要使內核支持proc文件系統,並將其掛接到根文件系統的/proc目錄
下。
    下表所列的文件或符號連接會出現在/proc目錄下,但並不詳盡,具體都包含那
些,取決於你的內核配置和具體的硬體設備。

名稱 功能
apm 高級電源管理信息。
buddyinfo Buddy演算法內存分配信息。
cmdline 內核的命令行參數。
config.gz 當前內核的.config文件。
cpuinfo cpu信息
devices 可以用到的設備(塊設備/字元設備)
diskstats 磁碟I/O統計信息。
dma 使用的DMA通道
execdomains 執行區域列表。
fb Frame buffer信息
filesystems 支持的文件系統
interrupts 中斷的使用情況,記錄中斷產生次數。
iomem I/O內存映射信息
ioports I/O埠分配情況
kcore 內核核心映像,GDB可以利用它查看當前內核的所有數據結構狀態。
key-users 密鑰保留服務文件
kmsg 內核消息
ksyms 內核符號表
loadavg 負載均衡信息
locks 內核鎖
mdstat 磁碟陣列狀態
meminfo 內存信息
misc 雜項信息
modules 系統已經載入的模塊文本列表
mounts 已掛接的文件系統列表
partitions 磁碟分區信息
pci 內核識別的PCI設備列表
self 訪問proc文件系統的進程信息
slabinfo 內核緩存信息
splash splash信息
stat 全面統計狀態表
swaps 交換空間使用情況
uptime 系統正常運行時間
version 內核版本
vmstat 虛擬內存統計表
zoneinfo 內存管理區信息

                              表2-6-1

下表所列的目錄會出現在/proc目錄下,但並不詳盡,具體包含那些,取決於你
的內核配置和具體的硬體設備。


名稱 功能
[number] 進程信息
acpi 高級配置與電源介面
asound ALSA音效卡驅動介面
bus 系統中已安裝的匯流排信息
dirver 空目錄
fs 空目錄
ide IDE設備信息
irq 中斷請求設置介面
net 網路各種狀態信息
scsi SCSI設備信息
sys 內核配置介面
sysvipc 中斷的使用情況,記錄中斷產生次數。
tty tty驅動信息
      表2-6-2



        
    proc文件系統的詳細內容可以通過執行 man proc命令獲得,這裡就不再進行更為詳
細的介紹了。


2.6.2 sysfs文件系統
    與proc文件系統類似,sysfs文件系統也是一個不佔有任何磁碟空間的虛擬文件系
統。它通常被掛接在/sys目錄下。sysfs文件系統是Linux2.6內核引入的,它把連接在系
統上的設備和匯流排組織成為一個分級的文件,使得它們可以在用戶空間存取。其實
sysfs是從proc和devfs中劃分出來的。
/sys目錄下會包含下表所列的目錄,但並不詳盡,不過具體內容還取決於內的配
置和具體的硬體設備。
名稱 功能
block 塊設備
bus 系統匯流排
class 設備組
devices 系統設備
firmware 固件
kernel 內核
module 內核模塊
power 供電系統
      表2-6-3


講述sysfs文件系統各目錄的詳細內容已經超出本文的範圍,感興趣的讀者可以查看
有關Linux驅動程序開發的書籍。

2.6.3 devfs文件系統
    devfs,也叫設備文件系統(Device Filesystem),設計它的唯一目的就是提供一
個新的(更理性的)方式管理通常位於/dev的所有塊設備和字元設備。典型的 /dev
樹包含數百個塊特殊文件和字元特殊文件,它們全都在根文件系統上。每個特殊文
件都可以讓用戶空間進程輕鬆地與內核設備實現交互。舉例來說,通過對這些特殊
文件執行操作,你的X伺服器就能夠訪問視頻硬體,fsck可以執行文件系統檢驗,lpd
可以通過并行埠向印表機發送數據。
實際上,通常Linux和Unix更「酷」的方面是,設備不是簡單地隱藏在晦澀的
API 之後,而是真正地與普通文件、目錄和符號鏈接一樣存在於文件系統上。因為
字元和塊設備是映射到普通文件系統名稱空間的,我們通常可以用有意義的方式來
與硬體交互,可以僅使用標準 Unix 命令,如 cat 和 dd。除了有趣之外,這還使我
們有更強的能力,並提高生產力。
下表所列的文件或符號連接可能會出現在/dev目錄下,但並不詳盡,具體內容取
決於你的具體硬體設備。
名稱 功能
audio 音品設備
cdrom[0-9] cdrom設備,這往往是一個符號連接
console 系統控制台
core 內核鏡像,為/proc/kcore的符號連接
dmmidi 固件
dsp 內核
dvd dvd設備,這往往是一個符號連接
fb Frame buffer,一般為/dev/fb0的符號連接
fb0 Frame buffer設備
fd 文件描述符,/proc/self/fd的符號連接
fd[0-9]+ 軟盤設備
floppy 軟盤設備,一般為fd[0-9]的符號連接
full 滿設備,任何寫入操作都會失敗,並把errno設為ENOSPC,以表示沒有剩餘空間。
fuse 用戶空間的虛擬文件系統
hd[a-z][1-9]+ IDE硬碟
sd[a-z][1-9]+ SCSI或SATA硬碟
hpet HPET設備
initctl 用戶與init進程交互的通道。
kmem 存取經過內核虛擬之後的內存
kmsg 任何對該文件的寫入都將作為printk的輸出
log syslog的本地套接字
loop[0-9] 迴環設備,一個磁碟文件模擬一個塊設備。
lp[0-9] 印表機
md[0-9] RAID設備
mem 直接存取物理內存
midi MIDI設備
mixer 混音器
null 控設備。任何寫入都將直接被丟棄,任何讀取都將得到EOF
parport[0-9] 並口
port 存取I/O埠
ppp ppp撥號設備
psaux PS/2滑鼠
ptmx 所有PTY master的復用器
pty[a-z]+[1-9]+ 偽終端,用於創建ssh等登陸會話
ram[0-9]+ RAM disk,initrd只能使用ram0
ramdisk ram0的符號連接
random 隨機數發生器。完全有用戶的輸入來產生隨機數。如果用戶停止所有動作,則停止產生隨機數。
root 根分區,這是一個到根分區設備的符號連接。
rtc 實時時鐘
stderr 標準錯誤輸出,/proc/self/fd/2的符號連接
stdin 標準輸入,/proc/self/fd/0的符號連接
stdout 標準輸出,/proc/self/fd/1的符號連接
tty[1-9,a-z]+ tty虛擬控制台,tty為當前控制台
ttyS[0-9] 串口
urandom 更快,但是不夠安全的隨機數發生器。
vcs[1-9,a-z]+ 虛擬控制台的文本內容,一一對應。
X0R /dev/null的符號連接
XOR /dev/null的符號連接
zero 0位元組源,可以讀取到無限多的0位元組。
 表2-6-4


下表所列的目錄可能會出現在/dev目錄下,但不是全部,具體情況與你的內核配
置和硬體設備有關。

名稱 功能
cpu cpu信息
disk 磁碟/光碟信息,裡面的內容為具體設備的符號連接
input 設備組
mapper RAID和LVM控制介面
net VMware和Qemu等使用的虛擬網卡
pts devpts文件系統掛載點,用於實現偽終端
raw 裸設備操作
shm Linux獨有的tmpfs文件系統掛接點。
snd 音效卡控制介面
 表2-6-5


    devfs文件文件系統是內核自動掛接的,當掛接好devfs文件系統后,才能正確執
行init程序。Linux上devfs文件系統與後面講述的tmpfs文件系統使用相同結構。

2.6.4 tmpfs文件系統
    tmpfs文件系統是Linux特有的文件系統,唯一的標準掛接點是/dev/shm。當然,用
戶可以將其掛接在其他地方。
    tmpfs有些像虛擬磁碟(ramdisk),但不是一回事。說其像虛擬磁碟,是因為它
可以使用你的RAM,但它也可以使用你的交換分區。傳統的虛擬磁碟是一個塊設
備,而且需要一個mkfs之類的命令格式化它才能使用。tmpfs是一個獨立的文件系
統,不是塊設備,只要掛接,立即就可以使用。
    tmpfs的大下是不確定的,它最初只有很小的空間,但隨著文件的複製和創建,
它的大小就會不斷變化,換句話說,它會根據你的實際需要而改變大小;tmpfs的速
度非常驚人,畢竟它是駐留在RAM中的,即使用了交換分區,性能仍然非常卓越;
由於tmpfs是駐留在RAM的,因此它的內容是不持久的,斷電后,tmpfs的內容就消失
了,這也是被稱作tmpfs的根本原因。
    有效的使用tmpfs可以極大的提高應用程序或整個系統的性能。有關tmpfs的詳細
內容,還請讀者參閱其他相關著作,畢竟本文講述的是一個Linux發行版的開發。

2.6.5 usbdevfs文件系統
    顧名思義,usbdevfs就是USB設備文件系統,它是一個動態生成的文件系統,有
些類似於proc文件系統。它的標準掛接點是/proc/bus/usb,當然,也可以掛接到其他
地方。它主要用於:用戶級驅動、即插即用、提供USB設備信息、應用程序輪詢
USB設備的變化等。

2.6.6 devpts文件系統
    devpts文件系統為偽終端提供了一個標準介面,它的標準掛接點是/dev/pts。只要
pty的主複合設備/dev/ptmx被打開,就會在/dev/pts下動態的創建一個新的pty設備文
件。掛接時,UID、GID及其工作模式會指定給devpts文件系統的所有pty文件。這可
以保證偽終端的安全性。
    討論devpts文件系統的詳細內容,已經超過本文範圍,還請讀者參考其他專
著。

2.7 結束語
    貫穿Linux的整個文件組織結構,無不洋溢著那繼承自Unix的深厚的文化底蘊,
美不勝收。使我不得不感嘆,Linux是多麼偉大的一個操作系統。正是由於這些,
Linux才長久不衰,越發顯得青春洋溢,讓我們這些熱愛Linux的人為其流連忘返。
    到了這裡,對於Linux的文件組織結構,我相信各位讀者應該有了感官上的認識
了,我也再次感謝你,為了Magic Linux,能夠堅持將這些醜陋的文字讀到這裡。在
下一章里,我將講述如何利用本章與上一章的知識,來構建一個能夠工作的基本系
統。
(未完...待續...)



[火星人 via ] 想參與linux社區開發的進來已經有135次圍觀

http://www.coctec.com/docs/linux/show-post-171253.html