Linux就這個範兒 第16章 誰均可以從頭再來--從頭開始編譯一套Linux系統 nsswitch.conf配置文件html
朋友們,今天我對大家說,在此時此刻,咱們雖然遭受種種困難和挫折,我仍然有一個夢想。
……
我夢想有一天,這個國家會站起來,並真正實現其信條的真諦:‘咱們認爲這些真理是不言而喻的:人人生而平等。’
……
我夢想有一天,幽谷上升、高山降低,坎坷曲折之路成坦途,聖光披露、照滿人間。
——馬丁·路德·金
這有點扯遠了,我確定是比不上馬丁·路德·金的。不過我曾經也有一個夢想,就是:當個人電腦一開機時,五星紅旗迎風飄揚,閃閃的紅星放光芒。雖然你立刻就能想到:修改一下開機畫面就好了。不過個人夢想是有一天我能夠開發出本身的操做系統,並且這個夢想伴隨了我十多年。直到我養家、娶妻、生子,才慢慢地開始忘卻……由於生活太TM不容易了……
通過這麼多年工做上的磕磕絆絆與不斷地學習,愈加地以爲本身的能力與夢想愈來愈遠也是最終放棄它的主要緣由。這或許就是知道的越多,不知道的也越多罷。不過在追逐夢想的同時,也逐漸解開了我曾經的很多疑惑。
編譯器可以將源代碼轉化爲能夠運行的程序,但是編譯器也是程序,編譯器怎麼來的?程序須要運行在操做系統之上,編譯器也是程序,操做系統又是靠編譯器編譯出來的,到底誰先誰後啊?一個操做系統須要具有哪些素質才能運行程序,編譯程序?我想你也可能會有這個疑問!這基本上算是計算機世界的「雞」和「蛋」的問題,只不過在這個世界裏這個問題有答案。
這一章裏咱們將要從頭編譯一套Linux系統,順便一一爲你解答這些問題。這一章大致上會分爲三個部分。能夠將咱們要編譯的Linux比做一個「嬰兒」。第一部分是準備環境,也就是爲咱們即將出生的「嬰兒」準備一個功能齊備的產房;第二部分講述做爲一個能夠獨立運行的Linux系統所必須具有的基本元素,爲咱們剛剛出生的「嬰兒」準備一張溫暖的牀;第三部分着重講解Linux內核的配置和編譯過程,爲咱們即將出生的「嬰兒」塑造一顆不同凡響的心房。
本章的內容源自LFS,可是高於LFS,由於咱們講述了LFS所沒有告訴你的東西,而這些正是你所疑惑的。LFS是Linux From Scratch的縮寫,翻譯過來就是Linux從零開始。它是一個Linux發行版,可是很特別,實際上只是一本電子書,告訴你如何從頭至尾編譯一個Linux系統。
好了,咱們開始吧!mysql
16.1初識工具鏈——準備環境的必備工具
等等,在正式開始以前,我還要讓你瞭解一個重要的知識,那就是工具鏈。工具鏈是咱們用來準備環境的一個必備工具。它是編譯器、鏈接器、程序庫和一些其餘輔助工具的集合。爲接下來打造編譯Linux的環境提供工具上的支持。正所謂「工欲善其事必先利其器」之所在。咱們須要的工具鏈,能夠說得上是編譯器、鏈接器、程序庫和Linux內核的四角戀愛故事,故事的內容天然是曲折而又精彩。那麼就且聽我細細道來罷。linux
16.1.1 編譯器
編譯器這個東東其實不用多解釋的,就是將源代碼翻譯成對應的機器代碼的工具。可是,編譯器直接輸出的代碼是不能直接執行的,由於即沒有安排好執行順序也沒有指定從哪裏開始。正是由於這樣,編譯器輸出的文件通常被稱爲目標文件。
Linux上使用的名爲gcc的編譯器集合,全稱是GNU Compiler Collection。它包含了C、C++、Objective-C、Fortran、Java、Ada等語言。同時也提供了一些程序庫,如:libstdc++、libgcj,……。gcc仍是一個開放框架,人們能夠很是容易地利用gcc實現本身設計的編程語言,而且使他們設計的語言成爲一個編譯型語言。
gcc的C編譯器是Linux的標準編譯器。Linux內核徹底依賴於gcc,其餘編譯器不能編譯Linux內核。另外,因爲ABI(Application Binary Interface)的不兼容,其餘編譯器也不適合Linux上的大多數軟件的編譯,尤爲那些使用C++做爲開發語言的軟件系統。目前IntelC/C++編譯器開始兼容gcc的ABI,所以如今能夠採用Intel C/C++編譯器編譯Linux上的軟件,可是內核不行。c++
16.1.2 鏈接器
剛纔說過,編譯器生成的機器代碼是不能執行的,由於沒有安排好執行順序也不知道從哪兒開始。這須要鏈接器來幫忙。鏈接器負責將編譯器生成的機器代碼進行排序並告訴計算機(嚴格來說是操做系統)從什麼地方開始執行。同時鏈接器還要負責一些其餘事情,好比程序須要向屏幕輸出一些內容,那麼如何操做也是由鏈接器告訴程序的。
Linux中並無提供單獨的鏈接器。不過GNU組織提供了一個名爲binutils的工具包,它包含了一個名爲ld的鏈接器,Linux使用的就是它。
從binutils這個工具包的名字上看,應該是一個二進制工具包,實際上也是這樣。它包含了彙編器、反彙編器、elf可執行文件分析器等重要工具。Linux內核中那不多量的彙編代碼就須要這個工具包提供的彙編器進行彙編。所以這是咱們必備的工具。程序員
16.1.3 程序庫 glibc->gnu c library
程序庫其實也不用多解釋的,由於咱們都很「懶」,因此咱們在寫程序的時候都喜歡找擁有各類功能的程序庫來知足須要。由於好多有用的算法和功能別人都實現了,咱們是沒有必要從新造輪子的。做爲C語言的程序員,最常常擺弄的程序庫實際上是兩個。一是C標準庫,二是操做系統的API。
Linux操做系統很霸氣,它將C標準庫和操做系統API經過一個名爲glibc的程序庫一同提供了。所以不少時候Linux上的程序員是分不清哪些函數是C標準庫,哪些是系統API的。
前面說過,鏈接器能夠告訴程序如何向屏幕輸出內容,這是它知道glibc程序庫提供了這個功能,讓程序調用glibc提供的相關功能實現的。
既然glibc提供了API,那麼也就意味着Linux上的全部程序都要依賴glibc,這包括我前面提到的gcc和binutils了。並且既然是API就必定與Linux的內核有依賴關係。
還要說一句的是,Linux系統中glibc不是惟一選擇。在嵌入式Linux中好多時候使用的是uClibc。若是你足夠強大,也能夠本身提供相似的東西,以決定提供哪些功能給用戶,或者簡化哪些功能的實現。這或許就是Linux最引人入勝的地方了,由於一切均可以隨你所願。正則表達式
http://www.cnblogs.com/MYSQLZOUQI/p/5257200.html算法
glibc庫是什麼?沒有glibc庫,就沒有Linux。咱們平時用過的malloc和strcpy等函數
都是glibc這位仁兄提供的。除此以外,它還提供了網絡編程中要用到的Socket API接口。以前曝光的glibc庫漏洞sql
glibc->gnu c libraryshell
glibc版本數據庫
rpm -qa |grep glibc
glibc-2.12-1.166.el6_7.3.x86_64 glibc-headers-2.12-1.166.el6_7.3.x86_64 glibc-2.12-1.166.el6_7.3.i686 glibc-devel-2.12-1.166.el6_7.3.x86_64 glibc-common-2.12-1.166.el6_7.3.x86_64
16.1.4 工具鏈——破解奇特的四角戀
到了這裏,四角戀的三個主角已經一一登場了。第四個就是Linux內核了。這個很少解釋,由於自知能力有限,這一生我都解釋不完。其實Linus本人如今都沒法詮釋Linux,這跟你的父母如今沒法詮釋你的一切是同樣的道理。
這個四角戀的關係是這樣的:glibc須要Linux內核來決定提供什麼樣的功能;gcc和binutils須要glibc來提供基本的功能實現,這樣也就將它們綁定在具體的Linux內核之上;Linux內核須要gcc和binutils來完成編譯和鏈接使得本身可以運行;glibc須要gcc和binutils將源代碼變成可供別人乃至gcc和binutils使用。這個顯然有點亂,咱們看一下它們的關係圖,見
圖16.1:
從圖16.1中能夠明顯地看出,除glibc與Linux內核(Linux內核本身實現一切功能)之間是單向依賴以外,其餘的都是雙向依賴。這顯然就是一個死結。若要從頭至尾編譯Linux就必須先解開這個死結,而且最後還要從新構成這個死結。如何作到呢?使用工具鏈技術。
首先咱們要清楚一件事情,就如今所能獲得的全部工具,要編譯一個操做系統,是在另一個操做系統之上完成的。這個「另一個操做系統」一般也被稱之爲HOST系統,或宿主系統。被編譯的操做系統一般被稱爲TARGET系統,或目標系統。其實任何流行的操做系統均可以做爲宿主系統,這章內容的宿主系統是CentOS 6.4。固然你也能夠選擇其餘系統,甚至Windows也能夠(稍微有點難度)。另外,在64位時代我選擇編譯一個64位的Linux,爲了簡單起見我選擇了64位的宿主系統,並且也沒有考慮要兼容32位系統。讓32位系統一邊玩去吧!
工具鏈就是從宿主系統中解開四角戀並在目標系統中造成新的四角戀的中間工具。它提供gcc、glibc、binutils的完美替身去欺騙Linux內核,從而完成這個過程的轉換。
工具鏈實際上是一種被稱爲「交叉編譯」的技術,它不但在相同架構的機器上完成這種「四角戀」的遷移,還能夠在不一樣架構的機器之間作這種轉換。所以掌握好工具鏈技術也是咱們全部程序員的必修課程。
16.2 準備環境
好了,我想我應該解釋清楚了一些基礎概念。那麼接下來開始正式進入準備環境的階段。這裏我先作一些假設。假設你已經徹底熟練了Linux系統的操做;假設你對C語言有一些瞭解;假設你是Linux最忠實的粉絲……。
這也是最初始的階段,去打造一個工具鏈。這就至關於爲咱們即將出生的Linux打造一個功能齊備的產房。在任何狀況下都可以保證它的順利出生。
這一階段也是很是重要的階段。在這個階段所發生的錯誤都會嚴重影響到咱們即將要編譯的新的Linux系統,甚至會致使咱們沒法完成這一目標。因此須要很是謹慎,確保每個環節都準確無誤。
16.2.1 宿主系統環境
無論怎麼樣,宿主系統的環境咱們仍是要設定一下的。主要是爲了方便咱們後面的操做。
首先是要準備一個獨立的磁盤分區,通常2G左右就夠了。若是你以爲有點麻煩,那麼有2G以上的自由空間也行。爲新的Linux劃分點交換空間也是必然的,多大就看你的我的喜愛。我如今假設你劃分了一個獨立的分區。那麼首先就要掛接,掛接點是什麼地方,本身決定就行。我掛接到了/mnt/m13目錄下。
而後在新的分區上建立兩個目錄,分別是toolchain和sources,分別用於工具鏈和存放源代碼。源代碼列表我就不列舉了,由於接下來你都會看到。至於你選擇何時下載這些源代碼,隨你我的喜愛。我也不能保證我所使用的軟件包都是最新的,其實最新的也許是不穩定的。
以後就是在你的宿主環境的根目錄下建立一個到toolchain目錄下的符號鏈接。至於爲何這麼作,其實就是爲了方便。若是你不嫌麻煩,徹底能夠忽略這個步驟。可是我強烈建議要這麼作,由於以後會真的很麻煩。我使用的命令是:
# In-sv/mnt/m13/toolchain/toolchain
此外,我是一貫不主張直接使用root帳號的,因此還要添加一個獨立的用戶用來編譯這個新生的Linux系統。這裏最重要的一個緣由就是不會由於某一個誤操做破壞了宿主系統。將toolchain和sources目錄的擁有者更改成你新添加的用戶,不然你也沒法更動這個目錄的內容,這顯然不是你想要的。當添加完新的用戶就切換到新用戶環境下。必定記得這麼作,由於下面的操做必須是針對這個新用戶環境的。
因爲咱們要編譯一個64位版本的Linux,那麼還須要在/toolchain目錄中建立一個lib64子目錄,同時在/toolchain/下創建一個名爲lib的到它的符號連接。這個設定很重要,就是爲了「欺騙」。這是一種善意的欺騙,若是你是一個一直都是說實話的人,我保證你找不到一個你喜歡的好姑娘;)
修改環境變量PATH,操做是這樣的:
$ export PATH=/toolchain/bin:$PATH
PATH環境變量指定了shell命令的默認搜索路徑。這樣設定就是當咱們工具鏈中的工具生成以後,默認執行的是它們,而不是宿主系統自帶的。這也是解除四角戀的開始。
宿主系統環境的準備就這麼多了,是否是簡單得出乎你的意料了?不要緊,接下來就沒那麼簡單了。
16.2.2 生成工具鏈的binutils
應該最早生成的是binutils。由於在生成gcc和glibc時,它們會檢測鏈接器和彙編器的特性來決定本身是否須要開啓某些特性。須要執行的全部命令以下:
$ tar vxf binutils-2.22.tar.bz2 $ mkdir binutils-build $ cd binutils-build $ ../binutils-2.22/configure\ --prefix=/toolchain--disable-nls--disable-werror\ --target=x86_64-mgc3-linux-gnu $ make-j $ make install
整個過程不是很難理解。你或許會問新建一個binutils-build目錄來作神馬?這是官方文檔說這樣作的,至少遵循官方建議的方式不會出現什麼錯誤,因此照作就能夠了。至於執行configure的命令時一些命令參數的含義我解釋一下:
--prefix=/toolchain
其實這個參數咱們在前面的章節中是介紹過的,就是要告訴configure腳本,把binutils軟件包中的程序安裝到/toolchina目錄中,也就是/mnt/m13/toolchain。
--disable-nls
這個參數禁止了國際化(一般簡稱il8n)。此時根本不須要國際化支持。
--disable-werror
這個參數能夠防止因爲你的系統提供的gcc在產生警告事件時中止建立過程。
--target=x86_64-mgc3-linux-gnu
這個參數用來聲明目標系統的名稱,x86_64-mgc3-linux-gnu是MagicLinux3.0系統的名稱。同時這也是進行交叉編譯時的重要概念。當指定這個參數時,安裝的程序會帶有x86_64-mgc3-linux-gnu的前綴,這樣就能夠與宿主系統的程序進行區分。
我在執行make的時候,帶有一個-j選項。這個選項本書在前面的章節也是講過的,這裏複述一次。這個選項是告訴make採用多任務方式並行生成目標。如今已是多核時代了,因此這個命令選項你們仍是經常使用爲好,能夠極大地縮短編譯Linux這種大項目的時間。另外,make的多任務模式比較吃內存,因此內存小的能夠考慮在-j後面添加一個數字來代表最多啓動多少個任務。
16.2.3 生成工具鏈的gcc
鏈接器如今準備好了,並且咱們不能立刻使用它,由於咱們尚未本身的glibc。也正由於如此等咱們生成glibc以後還要再次生成gcc,咱們以前生成binutils也要這樣處理,由於如今還沒法與宿主系統徹底脫離開來。
須要執行的全部命令以下:
$ tar jvxf gcc-4.6.2.tar.bz2 $ cd gcc-4.6.2 $ tar jvxf../mpfr-3.1.0.tar.bz2 $ mv-v mpfr-3.1.0 mpfr $ tar jvxf../gmp-5.0.2.tar.bz2 $ mv -v gmp-5.0.2 gmp $ tar zvxf../mpc-0 .9.tar.gz $ mv-v mpc-0.9 mpc $ cd.. $ mkdir gcc-build $ cd gcc-build $ ../gcc-4.6.2/configure --prefix=/toolchain\ --target=x86_64-mgc3-linux-gnu—disable-nls\ --disable-shared --disable-multilib-disable-decimal-float\ --Disable-threads—disable-libmudflap—disable-libssp\ --disable-libgomp—disable-libquadmath\ --disable-target-libiberty—disable-target-zlib\ --enable-languages=c --without-ppl –without-cloog\ --with-mpfr-include=$(pwd)/../gcc-4.6.2/mpfr/src\ --with-mpfr-lib=$(pwd)/mpfr/src/.libs $ make-j $ make install
須要敲入這麼多命令,真夠唬人的,其實很簡單。
首先,當今的gcc必須依賴mpfr、gmp和mpc這三個高精度數學運算庫,因此最開始的命令是將這些庫的源代碼放入gcc的源代碼的路徑下。
接下來就是對源代碼的配置和make過程了。我解釋一下configure程序所使用的一些特殊參數:
--target=x86_64-mgc3-linux-gnu
還記得在生成binutils時用的這個參數嗎?當給定這個參數時configure程序先會去查找全部可用的以x86_64-mgc3-linux-gnu做爲文件名前綴的程序,用於確保新生成的gcc可以與它們配合使用。它會找到咱們以前生成的鏈接器和彙編器等工具,gcc在編譯別的軟件時是要調用它們完成一些彙編和鏈接過程的。爲何可以找到呢?別忘了咱們以前是設定過$PATH這個環境變量的。若是你以前忘記設定了,那麼這個時候所生成的gcc就會有錯。
--disable-……—withou-……
這些參數都是爲了關閉gcc的一些特性,由於對於如今這個gcc是不須要的,這樣也能節省不少時間。
--enable-languages=c
這個參數是說只編譯C編譯器,由於如今只須要C編譯器。
--with-mpfr-include=$(pwd)/../gcc-4.6.2/mpfr/src
這個參數說明mpfr的頭文件搜索路徑,默認狀況下會搜索宿主系統的的頭文件路徑,這是不但願的。尤爲是宿主系統沒有提供mpfr時,就會報錯。
--with-mpfr-lib=$(pwd)/mpfr/src/.libs
這個參數說明在鏈接gcc的C編譯器時,mpfr的庫文件位置,不然會選擇宿主的mpfr庫。
最後就是make和安裝了,不用多解釋。可是要注意,還須要作一些收尾工做。幹什麼?騙人。騙誰呢?接下來要生成的glibc。騙它什麼呢?騙它咱們有libgcc_eh.a這個文件。由於缺乏這個文件,生成glibc的時候會報錯,glibc須要它。可是咱們在生成gcc時,使用--disable-shared參數,這會致使沒法生成libgcc_eh.a這個文件。怎麼騙呢?作個符號鏈接到libgcc.a文件。它們功能差很少,下一步生成的glibc用它提供的功能就足夠了。
libgcc.a的文件路徑能夠經過這樣的命令得到:
$ x86_64-mgc3-linux-gnu-gcc—print-libgcc-file-name
若是你以前的操做沒有什麼錯誤,它必定在你的工具鏈路徑下。
16.2.4 生成工具鏈的glibc
前面說過glibc就是標準C庫和API,因此它是不會依賴什麼程序庫了,也正由於這樣,咱們如今能夠用剛剛生成的gcc來編譯它。不過glibc對Linux內核仍是有依賴。glibc與Linux內核的依賴實際上是很微妙的,它並不依賴於內核的任何二進制代碼。由於glibc與內核的溝通是經過系統調用實現的,因此glibc須要知道內核都提供了哪些系統調用。這就要求將內核的一些頭文件指定給它。順便說一句,同一系列的內核在系統調用上不會有太大變化,好比2.6系列和現在的3.0系列。咱們首先就給glibc提供內核的頭文件,所需執行的操做以下:
$ tar jvxf linux-3.1.6.tar.bz2 $ cd linux-3.1.6 $ make mroroper $ make headers_check $ make INSTALL_HDR_PATH=dest headers_install $ cp-rv dest/include/*/toolchain/include/
這些命令最終將Linux內核提供的系統頭文件複製到工具鏈的include目錄下。
先要補充說明一下,當前的glibc再也不支持i386體系了,所以它的開發者建議在生成glibc時,最好使用-march=i486這個編譯選項。可是要是說,上個世紀的東西該扔就扔了吧,直接使用-march=i686,至少我認爲有收藏古董愛好的仍是極少數人。不過這些選項在64位時代已經不合適了,因此我不過多介紹它了。若是你必定要抱着32位系統不放,那你本身研究吧:)
生成glibc須要下面這些命令:
$ tar vxf glibc-2.14.1.tar.bz2 $ mkdir glibc-build $ cd glibc-build $ ../glibc-2.14.1/configure--prefix=/toolchain\ --host=x86_64-mgc3-linux-gnu\ --build=$(../glibc-2.14.1/scripts/config.guess)\ --disable-profile—enable-add-ons—enable-kernel=2.6 --with-headers=/toolchain/include\ libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes $ make-j $ make install
rpm -qa|grep glibc 2.12
就我所使用的這個glibc版本,當執行到configure程序的時候必定會報告一個錯誤。說它找不到「cpuid.h」這個頭文件。由於咱們剛纔生成的gcc並不包含這個文件。可是glibc說不行,沒有它我不幹活。這怎麼辦?讓它閉嘴。由於這個時候咱們根本不須要這個功能。因此讓它閉嘴是最好的辦法。怎麼讓他閉嘴呢?有人說騙它,弄個「cpuid.h」文件騙它。學得還真快,不過咱們以前已經騙過它一次了(還記得libgcc_eh.a的事情嗎?)。要我說,一樣的方法不能用兩次,由於第二次不必定靈,因此最好是用其餘手段。個人手段是給它吃「迷幻藥」,這個夠惡毒吧,千萬別說我卑鄙,由於我也很無奈。
「迷幻藥」是這麼下的。在glibc源代碼路徑下的sysdeps/i386/子路徑下也有一個configure程序。它就是報錯的源頭。細心的你會發現,我一直在說i386過期了,爲何又跟i386扯上關係了?緣由是代碼複用,64位系統也是用這段代碼。用你習慣的編輯器打開這個configure文件,跳轉到第635行(也多是別的地方,我下載的代碼是在這裏),你會看到這樣的代碼:
ac_fn_c_check_header-mongrel「$LINENO」「cpuid.h」\
「ac_cv_header_cpuid_h」「$ac_includes default」
把它改爲這個樣子:
ac_fn_c_check_header_compile「$LINENO」「cpuid.h」「ac_cv_header_cpuid_h」
就好了。以後再執行咱們上面的configure程序就不會再報錯了。
configure程序各選項的含義以下:
--host=x86_64-mgc3-linux-gnu
這個參數跟咱們以前見到的--target正好是相反的,它說明了宿主系統是誰。你可能會問,宿主系統不就是我在使用的嗎?爲何還要指定呢?這就是關鍵所在了。若是不指定新的宿主系統,則如今就會使用當前宿主系統的編譯器和鏈接器生成glibc,那等於咱們以前所做的工做都白費。指定了這個參數後,就會使用咱們剛剛生成的gcc和binutils了。這是典型的交叉編譯方法。
--build=$(../glibc-2.14.1/scripts/config.guess)
這個參數用於指定軟件的系統平臺,當前對於工具鏈來說還談不上什麼平臺,就調用config.guess來進行猜想。
--disable-profile
忽略掉profiling信息相關的庫文件,咱們這個時候是不須要的。
--enable-add-ons
這個是告訴glibc使用附加的NPTL(本地POSIX線程庫)包做爲線程庫。
--enable-kernel=2.6
告訴glibc只支持2.6以上的內核,雖然咱們選擇了3.1.6的內核,可是爲了讓接下來所生成的程序可以在宿主系統中運行,仍是須要使用較低的內核版本。
--with-headers=/toolchain/include
告訴glibc所使用的系統頭文件路徑。
libc_cv_forced_unwind=yes和libc_c_c_cleanup=yes
其實說到這裏我有點很差意思了。爲何?這又是一次欺騙。須要警告你們的是,不會一點善意的「欺騙」可能得不到女人的芳心,可是老是欺騙會獲得女人的傷心。因此能夠這樣對待glibc,可是必定不要這樣對待你的女人。爲何還要欺騙glibc呢?由於它的configure程序默認會進行forcede_unwind和c_cleanup的功能測試。而進行這兩項測試須要用到鏈接器的功能。可是咱們剛剛生成的鏈接器,因爲尚未glibc是不能正常工做的,因此執行這兩項測試就必定會報錯使得沒法繼續。那沒辦法,誰讓glibc這麼事兒媽呢?這也警告一些事兒媽的女人,太事兒媽了是會被騙滴:)
16.2.5 解決工具鏈的一些問題
看來這個時候編譯器、鏈接器、程序庫都已經搞定了,是否是接下來就能開始編譯咱們的目標系統了呢?不行!目前的這個工具鏈還不能真正工做起來。不信咱們就作一個實驗試試。編寫一個簡單的C代碼,我用下面這些命令:
$ echo「main(){}」>ttt.c $ x86_64-mgc3-linux-gnu-gcc-B/toolchain/lib64 ttt.c $ readelf-l a.out
看看結果,是否是有一行相似下面的內容:
[Requesting program interpreter:/lib64/ld-linux-x86-64.so.2]
這是不對的。readelf是分析elf可執行文件格式的工具,「-1」選項是用來顯示可執行文件各段頭內容的,經過它能夠了解一個可執行文件的依賴關係。上面的結果代表新的編譯器產生的可執行文件仍是依賴於宿主系統的ld-linux-x86-64.so.2。這是glibc的一部分,換句話說剛纔生成的glib。根本不會被使用。另外還有一個問題就是當我使用x86_64-mgc3-linux-gnu-gcc來編譯「ttt.c」的時候必須指定參數「-B/toolchain/lib64」,告訴它C運行時庫在哪裏,不然就會報告找不到「crtl.o」等文件。這也是不行的。
第一個問題如今就須要解決。方法是經過gcc的specs文件。這個文件原本是沒有的,可是隻要存在,gcc就會按照它的指示辦事。這個文件怎麼寫呢?不用寫。gcc能夠幫你生成。經過命令:
# x86_64-mgc3-linux-gnu-gcc-dumpsecs>specs
就能夠生成。不過如今這個文件的做用跟gcc的默認行爲沒啥區別,因此要在它的基礎之上修改。修改有兩個地方。第一個地方是將相似:
*cPP:
%{posix:-D_POSIX_SOURCE}%{pthread:-D_REENTRANT}
這樣的內容修改爲這個樣子:
*cpp:
%{posix:-D_POSIX_SOURCE}%{pthread:-D_REENTRANT-isystem
/toolchain/include
這告訴gcc的默認頭文件搜索路徑是/toolchain/include。第二是將全部相似:
/lib/ld-linux.so.2和/lib64/ld-linux-x86-64.so.2
修改爲:
/toolchain/lib/ld-linux.so.2和/toolchain/lib64/ld-linux-x86-64.so.2
這告訴gcc要使用工具鏈的glibc。
修改好了以後,須要將specs文件複製到與libgcc.a文件相同的路徑(還記得前面說的獲取這個路徑的方法嗎?)。以後執行一下最開始的測試。若是修改得沒有錯誤,如今獲得的結果應該相似這樣的:
[Requesting program interpreter:/toolchain/lib64/ld-linux-x86-64.so.2]
若是結果有出入,那麼就檢查一下specs文件是否修改正確了。或者更前面的操做有錯誤。若是是前面的操做有錯誤,那就會很悲催,重新再來一次吧!
第二個問題怎麼解決呢?不是很好解決,只能從新生成binutils和gcc了。爲何不在第一次生成binutils時就解決這個問題呢?由於那個時候尚未glibc,因此那個時候無法解決。另外。由於解決了第一個問題,咱們第二次在生成binutils和gcc時就能夠使用工具鏈的環境了,這使得咱們新生成的binutils和gcc與宿主系統沒什麼關係了。
16.2.6 第二次生成工具鏈的binutils
第二次生成工具鏈的binutils與第一次會有本質區別。第一次使用了宿主系統的編譯器和鏈接器,此次要使用咱們本身的了。所以相關的編譯參數會有很大不一樣。使用以下命令:
$ CC=「x86_64-mgc3-linux-gnu-gcc-B/toolchain/lib64」\ AR=x86_64-mgc3-linux-gnu-ar RANLIB=x86_64-mgc3-linux-gnu-ranlib\ ../binutils-2.22/configure--prefix=/toolchain--disable-nls\ --with-lib-path=/toolchain/lib64 $ make-j $ make install
此次沒有指定--target參數,由於咱們選擇的編譯器和鏈接器與目標系統是一致的,因此不用考慮交叉編譯問題。其餘新增參數含義以下:
CC=「x86_64-mgc3-linux-gnu-gcc-B/toolchain/lib64」
這修改了Makefile的$(CC)變量,也就是指定了編譯器是咱們工具鏈的。接下來的「AR」和「RANLIB」的做用是相同的,很少解釋了。
--with-lib-path=/toolchain/lib64
這個就解決了前面所說的「第二個」問題。告訴鏈接器程序庫的搜索路徑是什麼地方。
雖然咱們安裝完了新的binutils了,並且也與宿主系統沒有半毛錢關係了,可是咱們還得作一些有意義的工做。是什麼呢?看下面要執行的命令:
$ make-C ld clean $ make-C ld LIB_PATH=/usr/lib64:/lib64 $ cp-v ld/ld-new/toolchain/bin
這些命令的意思是這樣的。首先將開始生成的ld程序清除掉。而後使用新的編譯選項重新編譯。這個新的編譯選項LIB_PATH能夠指定ld程序,也就是鏈接器的程序庫默認搜索路徑。這會致使一個名爲ld-new的程序被編譯出來(binutils的開發者想得很周到:)。最後複製到/toolchain/bin路徑下,以備後面的過程所使用。
16.2.7 第二次生成工具鏈的gcc
第二次生成工具鏈的gcc有點複雜。由於此次生成的gcc是要獨立於任何系統的,首先就得讓它規矩一點,不要再與誰勾勾搭搭了。要作到這一點能夠想像一下咱們聰明的祖先們是怎麼對付太監的。對,淨身!咱們先要給gcc淨身。怎麼淨,淨什麼呢?固然是惹禍的根——fixincludes腳本。在gcc的編譯過程會運行fixincludes腳原本掃描系統頭文件目錄,並找出須要修正的頭文件,而後把修正後的頭文件放到gcc專屬頭文件目錄裏。因爲gcc專屬頭文件會被優先搜索,結果就是gcc使用的頭文件是宿主系統的頭文件。這是一種好心辦壞事的行爲,雖然它並非必定「惹是生非」(或許找不到須要修正的頭文件),但仍是把它除掉最爲安全。經過修改gcc/Makefile.in文件來完成這個操做。將「./fixinc.sh」用「-c true」進行替換(只有一處是這麼寫的)。
然而gcc「惹是生非」的還不止一處(很堅強啊:)。咱們都知道,做爲C語言的程序都是以main()函數做爲程序的入口的。可是咱們已經知道,編譯器並無指定一個程序應該從那裏執行,這是由鏈接器肯定的。鏈接器怎麼就知道C語言的程序是從main()開始的呢?原來C編譯器要負責提供一些「啓動文件」,這些文件會告訴鏈接器程序的入口是main()函數,而不是end()函數。早期版本的gcc會默認根據--prefix參數中指定的路徑開始搜索「啓動文件」。可是從gcc4.3開始,就再也不提供這個特性了。因此這個禍根必須剔除。怎麼剔除呢?還有點麻煩,須要修改gcc的源代碼。不過不用緊張,代碼量不多。只要修改gcc/gcc.c文件就好了。對於4.6.2版的gcc,從第6385行開始,會看到這樣的代碼:
else if(*cross_compile ==‘0’) { add-prefix(&startfile-prefixes, concat (gcc_exec_prefix ?gcc_exec-prefix:standard-exec_prefix, machine_suffix, standard_startfile_prefix,NULL), NULL,PREFIX_PRIORITY_LAST,0,1); }
把它改爲這樣:
else if(*cross_compile==‘0’) { add_prefix(&startfile_prefixes, concat (gcc_exec_prefix ?gcc_exec_prefix:standard-exec_prefix, machine_suffix, standard_startfile_prefix,NULL), NULL,PREFIX_PRIORITY_LAST,0,1); Add_prefix(&startfile_prefixes, concat (standard_exec_prefix, machine_suffix, standard_startfile_prefix,NULL), NULL,PREFIX_PRIORITY_LAST,0,1); }
就能夠了。
不過彆着急,如今尚未「淨身」乾淨。如今的gcc對程序庫和頭文件的搜索路徑尚未改變。即使採用specs大法也是有問題的,雖然它可以改變程序庫的搜索路徑,可是對頭文件所搜路徑的更改只是增長了一個優先級。若是在指定的路徑中找不到指定的頭文件,則依然會從宿主系統中尋找,這樣依然沒法保持工具鏈的純淨。因此,仍是須要進行一番改造。方法是將gcc/config路徑下的linux.h及gcc/config/i386路徑下的linux.h、linux64.h和sysv4.h這四個文件中對程序庫的搜索路徑進行修正,增長/toolchain,並在它們的結尾處,添加一些宏定義。
修改是這樣的:尋找全部相似「/lib/ld」、「lib64/ld」或「lib32/ld」這樣的代碼,它們通常都具有「/usr」的開頭,若是有這個開頭,就用「/toolchain」替換,沒有就添加「/toolchain」。添加的宏定義以下面所示:
#undef STANDARD_INCLUDE_DIR #define STANDARD_INCLUDE_DIR 0 #define STANDARD_STARTFILE_PREFIX_1「」 #define STANDARD_STARTFILE_PREFIX_2「」
注意,每一個文件都要添加。
另外要補充說明一下。第一次生成gcc時採用的是交叉編譯法,而此次被稱爲本地編譯法。本地編譯法默認會採用bootstrap方式進行。這種方式會重複生成三次。就是用第一次生成的gcc再一次編譯本身,而後用第二次生成的gcc再重複一次。最後比較第二次和第三次的結果,這樣來確保編譯器能夠毫無差錯地編譯自身。這是有點很浪費時間的,出於節省時間的考慮,咱們要禁止使用這種方式。不過禁用bootstrap方式會有一個代價,就是沒法享有-fomit-frame-pointer優化所帶來的性能提高,這會致使後面的編譯過程所需時間加重。因此須要使用一個魚與熊掌兼得的方法,強制使用-fomit-frame-pointer優化。技巧是修改該gcc/Makefile.in文件,在「T_CFLAGS=」的後面添加「-fomit-frame-pointer」。
好了,通過這麼多的改造,就能夠生成gcc了。不過此次會比第一次提供的功能多一些,並且也會生成C++編譯器,由於後面須要。所使用的命令以下:
$ CC=「$x86_64-mgc3-linux-gnu-gcc-B/toolchain/lib/」\ AR=$x86_64-mgc3-linux-gnu-ar RANLIB=$x86_64-mgc3-linux-gnu-ranlib\ ../gcc-4.6.2/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-multilib\ --disable-bootstrap—disable-libgomp\ --without-ppl—without-cloog\ --with-mpfr-include=$(pwd)/../gcc-4.6.2/mpfr/src\ --with-mpfr-lib=$(pwd)/mpfr/src/.libs $ make-j $ make install
解釋一下以前沒有見過的參數:
--with-local-prefix=/toolchain
這個參數的目的是把/usr/local/include目錄從gcc的頭文件搜索路徑中刪除。這也是讓它與宿主系統相隔絕的一個環節。
--enable-clocale=gnu
由於此次引入了C++編譯器,這個參數是爲了確保C++程序庫在任何狀況下都使用正確的local模塊。由於選擇了不正確的locale模塊有可能會致使C++庫文件的ABI不兼容。
Enable-shared
這個參數是爲了可以正確生成glibc所必須的。由於前面咱們已經作了一個假的libgcc_eh.a文件來欺騙glibc了,可是到了生成正式系統時就不能用騙的了。
--enable-threads=posix
這個參數使得C++異常能處理多線程代碼。
--enable-__cxa_atexit
這個參數容許使用_cxa_atexit代替atexit來註冊C++對象的本地靜態和全局析構函數。這是爲了徹底符合標準對析構函數的處理規定。它會影響到C++的ABI,這確保了生成的C++共享庫和C++程序在其餘的Linux系統上也能使用。
--disable-bootstrap
這就是用來禁用bootstrap方式的選項。
如今一個全新的獨立於任何系統的gcc就生成了,擁有c和c++兩個編譯器。最後要執行一個畫龍點睛的操做,建立一個cc到gcc的符號鏈接。這能夠保持通用性,由於不少程序和腳本尋找的是cc而不是gcc。
16.2.8 豐富工具鏈的功能
如今咱們的工具鏈已經具有了編譯器、鏈接器和程序庫,它們都是針對3.1.6內核的,而且已經獨立於宿主系統。可是爲了可以最終生成咱們的目標系統,還須要對它進行一些完善。這須要表16-1所列出的這些軟件包。
表16-1
軟件包 |
說明 |
Tcl-8.5.10 |
這個東西跟電視機沒什麼聯繫,是工具命令語言的縮寫。主要給後面的測試程序提供支持 |
Expect-5.45 |
一個以Tcl語言做爲核心的工具。它能夠使得須要交互的程序具有非交互特性,好比passwd。不少測試框架都是從於它來實現功能 |
DejaGNU-1.5 |
這是一個測試框架。使用Tcl語言編寫,須要Expect的支持 |
Check-0.9.8 |
與DejaGNU相似,這是一個針對C語言的單元測試框架 |
Ncurses-5.9 |
很是著名的字符界面庫。能夠在字符界面實現窗口的繪製等 |
Bash-4.2 |
Linux下最爲流行的shell,也是Linux的標準shell。全部Linux系統都應該提供 |
Bzip2-1.0.6 |
一個基於bzip2算法的壓縮解壓縮工具。全部以.bz2結尾的文件都使用它來解壓縮 |
Coreutils-8.14 |
Linux系統的核心工具包。好比rm、mkdir、Is等都出自這個軟件包 |
Diffutils-3.2 |
文件比對工具,常常用於生成補丁文件 diff命令 |
File-5.09 |
檢測文件類型的工具 |
Findutils-4.4.2 |
就是著名的find工具 find命令 |
Gawk-4.0.0 |
Awk語言,編寫shell腳本時常用。用於處理文本文件 |
Gettext-0.18.1.1 |
系統的國際化和本地化的工具。Linux多國語言支持就靠它了 |
Grep-2.10 |
很是著名的基於正則表達式的文本搜索程序 |
Gzip-1.4 |
基於gzip算法的壓縮和解壓縮工具。全部以.gz結尾的文件須要使用它來解壓縮 |
M4-1.4.16 |
這是一個宏處理器,並內置了不少宏。是不少自動化工具的基礎設施 |
Make-3.82 |
很是著名的make工具 |
Patch-2.6.1 |
很是著名的打補丁工具,它的補丁文件來源於diff工具 |
Perl-5.14.2 |
很是經典的Perl語言 |
Sed-4.2 |
這是一個流式文本編輯器。用途很是多,主要用在shell腳本修改文本文件的場景 |
Tar-1.26 |
Tar包管理程序 |
軟件包 |
說明 |
Texinfo-4.13a |
一整套info文檔工具。Linux除了man幫助,還有更爲詳細的info文檔 |
Xz-5.0.3 |
這是一個基於LZMA算法的壓縮與解壓縮工具。有很高的壓縮比。以.xz結尾的文件使用它來解壓縮 |
Linux下help、man、info命令區別詳解
http://jingyan.baidu.com/article/75ab0bcbc7da3cd6874db26d.html
--help、man、info三個指令均爲Linux下的幫助指令格式,三個指令略有區別。
help命令用於顯示shell內部的幫助信息。help命令只能顯示shell內部的命令幫助信息。而對於外部命令的幫助信息只能使用man或者info命令查看。
man命令,經過man指令能夠查看Linux中的指令幫助、配置文件幫助和編程幫助等信息。man是在程序安裝的時候安裝的幫助文檔,能夠在系統的目錄下找到,若是軟件有配套的頁面,就能夠使用man來查找。
好比經過指令:ls /user/share/man咱們能夠看到不少man幫助文檔的存儲,咱們從中看到有不少歌man#文件,linux的一些man指令文檔就存在於這些文件內。
一個程序的man幫助文檔可能存在多個man中,好比咱們用指令:whatis man,查看到man的多個信息。而wahtis ifconfig說明ifconfig指令的幫助文檔存在於man8中。
whatis ifconfig
ifconfig (8) - configure a network interface
咱們用man ifconfig查看ifconfig的幫助文檔,咱們看到ifconfig左上角在man8中找到的相應幫助信息。而指令man man發現man在man1中就找到了,說明man手冊是按順序查找的。
info指令是man 指令的詳細內容。但man 使用起來要方便的多。一個man 只有一頁,而info老是將它們的內容組織成多個區段(節點),每一個區段也可能包含子區段(子節點)。info工具可顯示更完整的最新的GNU工具信息。一般man中若包含的信息概要在info中也有時,會有提示:「請參考info頁更詳細內容」。
這些軟件的編譯安裝都比較簡單。須要注意的地方是:第一,Tcl、Expect、DejaGNU這三個軟件的安裝順序不能變,由於有必定的依賴關係;第二,Check和Ncurses的安裝沒有必然順序,可是必須保證Nucrses是在其餘軟件以前安裝,由於有一些軟件依賴於它;第三,若是想要對這些軟件的正確性進行測試,則必須最早安裝Tcl、Expect、DejaGNU和Check,由於它們提供了測試用的框架。
有一些軟件安裝後要作一些調整。Tcl安裝完畢以後,爲了保持最大兼容性,須要建立一個「tclsh」到「tclsh8.5」的符號鏈接。由於當前版本的Tcl只安裝tclsh8.5做爲它的可執行程序,可是好多軟件使用tclsh來調用Tcl。Bash安裝後須要建立一個「sh」到「bash」的符號鏈接,由於做爲默認shell,不少軟件是直接調用「sh」而不是「bash」的。安裝Coreutils軟件包後,su命令不會被安裝,由於在普通用戶權限下不能安裝su命令。這就須要手動複製到工具鏈中。可是爲了保證能夠使用宿主系統的su命令,須要將它從新命名。
還有一些軟件在執行configure程序時須要使用一些參數來屏蔽或開啓某些功能,或者乾脆修改configure程序來保證它針對於工具鏈的純粹和有效。Expect的configure程序會強制它使用/usr/local/bin/stty,可是在咱們用工具鏈建立目標系統時這個程序路徑是不對的,因此找到這段內容,修改爲/bin/stty。編譯Ncurses時,應該關閉對ada語言的支持,由於工具鏈就沒提供這個語言。同時還要使用--enable-overwrite選項強制它將頭文件安裝到/toolchain/include路徑下,這能夠保證其餘軟件可以找到它。編譯Bash時使用--without-bash-malloc參數來禁止使用它自己提供的malloc函數,由於它有訪問越界bug。編譯Coreutils時要使用--enable-install-program=hostname參數,由於默認它是不安裝hostname這個工具的,可是Perl須要它。編譯Grep時須要使用--disable-perl-regexp參數來禁用Perl兼容的正則表達式,由於在編譯目標系統時它不能使用。同時還要使用--without-included-regex參數(pcre庫 perl compatible regular expression),由於若是不使用這個參數會破壞目標系統的glibc的正則表達式庫。
另外,在編譯Perl的時候須要作一些比較大的改動。主要是修改hints/linux.sh文件。將全部涉及/lib/libc.so.6或/lib/$libc的內容要冠以/toolchain前綴。還要在它的末尾添加以下內容:
locincpth=「」 loclibpth=「」 glibpth=「/toolchain/lib」 usrinc=「/toolchain/include」
這是爲了保證它只使用工具鏈的頭文件和庫。
16.2.9 整理工具鏈
此時此刻,咱們的工具鏈就已經打造完成了。不過還須要作最後的調整,這個過程或許你認爲沒什麼必要。可是這麼費力打造的工具鏈是徹底不止用於編譯最終的Linux系統的,它還能夠作好多好多有意義的工做。因此爲了便於移動和交流,對它進行必要的精簡是很是有意義的一件事情。
如今這個工具鏈可以精簡哪些內容呢?首先就是調試信息。Linux上的軟件經過源代碼編譯安裝的,大多都會帶有調試信息。這個調試信息很是龐大,每每比整個工具鏈還要大上幾倍。並且工具鏈的調試信息對咱們使用它的人也沒什麼意義,因此這個須要清理。
另一個須要清理的內容就是工具鏈中各類工具的幫助信息。這些信息也會佔據很大的磁盤空間,並且也沒有什麼實際用途。這些幫助信息能夠在不少地方找獲得。何況工具鏈須要運行在宿主系統中,每每宿主系統會提供這些幫助信息,因此工具鏈中的幫助信息就更加沒有什麼用處了。
所使用的命令以下:
# strip--strip-debug/toolchain/lib64/* # strip--strip-unneeded/toolchain/{,s}bin/* # rm-rf/tools/{,share}/{info,man,doc}
最後記得將toolchain目錄的擁有者所屬組都更改成root。這樣能夠防止工具鏈被破壞。並且接下來的過程將會一直使用root帳戶。雖然我很反對使用root,可是這是使用root的最好用例,由於這是要從頭至尾編譯Linux,那不也正是體現出root的本來含義的嗎?
16.2.10 小結
一個完整的工具鏈打造完畢了。這個須要花費極大的耐心和時間。可是工具鏈是很是有用的。你能想到工具鏈都能作什麼嗎?
有沒有想過,當一個全新的硬件平臺開發出來,如何給它安裝操做系統和軟件呢?這個時候須要工具鏈。用工具鏈來編譯目標平臺的操做系統和軟件,最終使得這個新的硬件平臺具有了完整的軟硬件體系。
一些沒有操做系統的硬件平臺如何爲它們開發軟件呢?好比諾基亞的非智能手機。這個時候須要工具鏈,在宿主系統上開發和編譯可以運行在它上面的軟件。這裏最多見的宿主系統就是Windows。諾基亞會提供給開發者一個工具鏈,用來開發能運行在他們手機上的軟件。
一些具有操做系統,可是沒有足夠大的屏幕,也沒有鼠標鍵盤的智能系統如何給他們開發軟件呢?好比大紅大紫的Android智能手機。咱們開發者都會從Google下載一個SDK,在Windows、Linux乃至Mac上開發Android程序。這個SDK也是一個工具鏈。
工具鏈是一個跨操做系統,跨硬件平臺開發的必備工具,也是想成爲一名優秀程序員的必修課程。咱們在建立這個工具鏈的時候發現,須要對編譯器、鏈接器甚至一些輔助的工具程序進行大量修改。也正由於這樣,當咱們在研究建立工具鏈的時候,會對這些程序作很深的研究才能達成咱們的目標。這也就使得咱們在研究工具鏈的時候,有足夠的理由去深刻研究那些平時咱們用得最多,但不瞭解其內部運做機理的程序。當你把這些都研究透徹以後,是否是之後遇到一些開發上的問題,就會得心應手呢?
好了,針對工具鏈的探討就到此結束了。咱們接下來還有很長的一段路須要走。你應該選擇休息一下子再繼續下面的內容。
16.3 生成目標系統的運行環境
從如今開始,就真正開始了編譯Linux系統的歷程,並且要使用root身份。或許在開始這一部份內容的時候,你就開始打Linux內核的主意了。不過這會讓你有些失望。如今還不是碰Linux內核的時候。這一階段所要作的事情是準備運行環境。主要是將工具鏈中的「四角戀」轉移到咱們的目標系統中,而且建立一個能夠正常運行的Linux系統的最小環境集合。能夠把這部份內容看作是爲咱們即將出生的Linux打造一張溫暖的牀。
另外。爲了可以讓咱們本身編譯的Linux系統具有通用性,就須要讓這個系統符合LSB規範。LSB是Linux Standards Base的縮寫。不過LSB只是Linux標準化領域中的事實標準,所以就目前的Linux世界來看,它依然是有些混亂的。可是若是可以符合LSB,那麼因爲它已是一個事實,因此就能夠作到最大程度的通用化。至於LSB都規定了什麼,咱們後面章節再作介紹。經過接下來的內容,能夠先體會一下LSB。
http://www.cnblogs.com/MYSQLZOUQI/p/5383594.html
16.3.1 準備工做
首先要作的準備工做就是準備特種文件系統(還記得「特種文件系統」那一章的內容嗎?)。在咱們準備好的磁盤分區上先要建立dev、proc、sys這三個目錄。
建立好三個目錄後,執行下面的命令:
# mknod-m 600 文件權限 /mnt/m13/dev/console c 字符設備 5 1 # mknod-m 666/mnt/m13/dev/null c 1 3
「mknod」這個命令是什麼做用我很少解釋,你們能夠man一下,實在不行Google一下。執行完這兩個命令以後,會在dev目錄下生成「console」和「null」這兩個重要的設備文件。這是爲了保證在udevd啓動以前,或者Linux以init=/bin/bash啓動時,這些設備節點能夠使用。
接着就是填充/dev目錄的內容。這個時候目標系統尚未udev,因此它裏面什麼都沒有,可是後面的步驟還很是須要它。怎麼辦呢?使用宿主系統的/dev。用下面的命令:
# mount-v--bind/dev/mnt/m13/dev
這是很典型的綁定掛接應用,咱們以前說過,但願你如今還記得。而後把其餘的特種文件系統都掛接到正確的位置:
# mount-vt devpts devpts/mnt/m13/dev/pts # mount-vt tmpfs shm/mnt/ml3/dev/shm # mount-vt proc proc/mnt/m13/proc # mount-vt sysfs sysfs/mnt/m13/sys
既然pts和shm都已經在dev目錄下了,爲何還要掛接一次呢?回想一下綁定掛接的特性就明白了。接下來地步驟更爲重要,由於咱們要進入chroot環境來構建這個新生的Linux系統的運行環境。chroot是一個程序,可以臨時改變系統的根目錄。正是利用這個特性,才使得咱們能夠很容易地構建目標系統的運行環境。使用以下命令進入這個chroot環境:
# chroot「/mnt/m13/」/toolchain/bin/env-i\ /sbin/service腳本也是這樣 HOME=/root TERM=「$TERM」PSl=‘\u:\w\$’\ PATH=/bin:/usr/bin:/sbin:/usr/sbin:/toolchain/bin\ /toolchain/bin/bash--login +h
這其中的第一個參數很顯然地就是將咱們準備的磁盤分區做爲新的根目錄來使用了,因此這個命令執行完畢以後,咱們的磁盤分區就會成爲根目錄。
env命令的參數「-i」是清除chroot的環境變量,這就保證目標系統不會受到宿主系統的影響。同時設置了新的HOME、TERM和PSl這三個變量。HOME是直接指定的,因此與宿主系統沒有關係。TERM使用了宿主的TERM內容,可是它不會對目標系統產生影響。PSl就是用於修改命令提示符的,隨便你怎麼設定。
有一個頗有趣的設定就是PATH變量,它與宿主系統的PATH變量相反,/toolchain/bin放在了最後,原理與宿主的PATH相同,由於隨着咱們的努力,工具鏈應該被逐步取代。
最後的參數是讓chroot環境使用工具鏈的bash做爲shell,而且增長了「+h」這參數來保證chroot環境的純碎。
當這條命令執行完畢以後,你會有一個吃驚的發現。命令提示符會顯示成「I have no name!」。若是是這樣就證實作對了,由於沒有建立/etc/passwd文件就會有這樣的提示符出現。
正確進入了chroot環境後,就須要建立目標系統的文件佈局了。這個佈局在LSB中是有規定的。執行下列命令:
# mkdir-pv/{bin,boot,etc/opt,home,lib,mnt,opt} # mkdir-pv/{media/{floppy,cdrom},shin,srv,var} # install-dv-m 0750/root # install-dv-m 1777/tmp/var/tmp # mkdir-pv/usr/{,local/}{bin,include,lib,sbin,src} # mkdir-pv/usr/{,local/share/{doc,info,locale,man} # mkdir-v/usr/,{,local/}share/{misc,terminfo,zoneinfo} # mkdir-pv/usr/{,local/}share/man/man{1..8} man1~man8 # for dir in/usr/usr/local;do In-sv share/{man,doc,info}$dir done # In-sv lib/lib64 && In-sv lib/usr/lib64 # mkdir-v/var/{lock,log,mail,run,spool} # In-run/var/run # In-sv/run/lock/var/lock # mkdir-pv/var/{opt,cache,lib/{misc,locate},local}
有一些程序使用了固化的絕對路徑,可是這些內容目前還不存在。爲了應付這些程序,咱們就用符號鏈接或空文件來「騙它」。固然,等到對應的軟件被編譯並安裝以後,這些符號鏈接或空文件會被真實的文件所替換掉。執行下列命令:
# In-sv/toolchain/bin/{bash,cat,echo,pwd,stty}/bin # In-sv/toolchain/bin/perl/usr/bin # In-sv/toolchain/lib/libgcc_s.so{,.1}/usr/lib # In-sv/toolchain/lib/libstdc++.so{,.6}/usr/lib # In-sv bash/bin/sh # touch/etc/mtab
爲了讓咱們的命令提示符可以正常一點,還須要建立/etc/passwd和/etc/group這兩個文件。當前沒有什麼文本編輯器能夠用,只能用命令來完成:
# cat>/etc/passwd<<「EOF」 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/dev/null:/bin/false nobody:x:99:99:Unprivileged User:/dev/null:/bin/false EOF # cat>/etc/group<<「EOF」 root:x:0: bin:x:1: sys:x:2: kmem:x:3: tty:x:4: tape:x:5: daemon:x:6: floppy:x:7: disk:x:8: lp:x:9: dialout:x:10: audio:x:11: video:x:12: utmp:x:13: usb:x:14: cdrom:x:15: mail:x:34: nogroup:x:99: EOF
這兩個文件的內容沒有什麼嚴格規定,只要符合格式就好。若是想讓這兩個文件的內容看上去很專業,能夠參考宿主系統的內容。
要想改變命令提示符,須要從新登陸才行,執行:
# exec/toolchain/bin/bash--login +h
還要建立一些日誌文件,由於沒有它們,是沒法記錄日誌的。執行下列命令:
# touch/var/run/utmp/var/log/{btmp,lastlog,wtmp} # chgrp-v utmp/var/run/utmp/var/log/lastlog # chmod-v 664/var/run/utmp/var/log/lastlog
其中:/var/run/utmp文件記錄當前登陸的用戶;/var/log/wtmp文件記錄全部的登陸和退出;/var/log/lastlog記錄每一個用戶最後的登陸信息;/var/loglbtmp文件記錄錯誤的登陸嘗試。
最後咱們要將Linux的聯機幫助信息(那個「男人」啊)安裝好。執行下面的命令:
# cd sources # tar vxf man-page-3.35.tar.gz # cd man-page-3.35 # make install
它必須在全部軟件安裝前被安裝好。由於只要稍晚一些安裝它,它就會將以前編譯安裝的軟件的聯機幫助信息覆蓋掉。其餘軟件不會有這樣的結果,它們會豐富它的內容。
16.3.2 安裝glibc
如今開始爲目標系統安裝必要的軟件。第一個就是glibc,由於它是全部軟件可以被編譯並安裝的基礎。
首先仍是要安裝內核的API頭文件,命令以下:
# make mrproper # make headers_check # make INSTALL_HDR_PATH=dest headers_install # find dest/include\(-name.install-o-name..install.cmd\)-delete # cp-rv dest/include/*/usr/include/
注意文件複製路徑的改變。並且此次也刪除了沒有必要的垃圾文件。
不過如今還不能立刻安裝glibc。有一個小問題,就是當咱們編譯完成後,執行安裝操做時,會執行一個叫作test-installation.pl的腳原本作一些完整性測試。但是咱們是使用工具鏈來編譯glibc的,這個完整性測試會對工具鏈中的glibc作測試,這會致使錯誤。所以咱們在安裝glibc以前,要對test-installation.pl腳本作一些調整,強制讓它測試咱們要安裝的glibc。另外,這個腳本還有一個bug,咱們也一同修正它。因爲這個環境沒有編輯器,因此須要執行必要的命令來進行修改。命令以下:
# DL=$(readelf-l/bin/sh|sed-n’s@.*interpret.*/toolchain\(.*\))$@\1@p’) # sed-i「s|libs-o|libs-L/usr/lib-Wl,-dynamic-linker=$DL-o}」\ scripts/test-installation.pl # unset DL # sed-i-e‘s「dbl」/&\&\&$name ne「nss_testl」/’
scripts/test-installation.pl
這些命令都幹了些啥,我就不講解了,想知道其中的祕密就好好學sed。這個東東在Linux系統中地位很重要。
接下來就能夠安裝glibc了,命令以下:
#../glibc-2.14.1/configure --prefix=/usr\ --disable-profile—enable-add-ons\ --enable-kernel=2.6 # make-j # cp-v../glibc-2.14.1/iconvdata/gconv-modules iconvdata # make -k check 2>&1|tee glibc-check-log -k忽略錯誤,繼續編譯 # touch/etc/ld.so.conf # make install
能夠看得出編譯選項已經少了不少了。多出來的步驟是用於對glibc進行一次全方位的測試。複製文件是爲了保證測試可以順利完成。生成/etc/ld.so.conf這個空文件是爲了保證在安裝glibc時它不會報錯。當glibc安裝完畢後,咱們還要對它進行必要的配置。
首先就是對不一樣語言的支持,使用以下命令:
# mkdir-pv/usr/lib/locale # localedef-i cs_CZ-f UTF-8 cs_CZ.UTF-8 # localedef-i de_DE-f ISO-8859-1 de DE # localedef-i de_DE@euro-f ISO-8859-15 de_DE@euro # localedef-i de_DE-f UTF-8 de_DE.UTF-8 # localedef-i en_HK-f ISO-8859-1 en_HK # localedef-i en-PH-f ISO-8859-1 en_PH # localedef-i en_US-f ISO-8859-1 en_US # localedef-i en_US-f UTF-8 en_US.UTF-8 # localedef-i es_MX-f ISO-8859-1 es_MX # localedef-i fa_IR-f UTF-8 fa_IR # localedef-i-i fr_FR-f ISO-8859-1 fr_FR # localedef-i fr_FR@euro-f ISO-8859-15 fr_FR@euro # localedef-i fr_FR-f UTF-8 fr_FR.UTF-8 # localedef-i it_tT-f ISO-8859-1 it_IT # localedef-i ja_JP-f EUC-JP ja_JP # localedef-i tr_TR-f UTF-8 tr_TR.UTF-8 # localedef-i zh_CN-f GB18030 zh_CN.GB18030 # localedef-i zh_CN-f UTF-8 zh_CN.UTF-8
多說幾句。在我國有一個強制標準,就是任何上市發行的簡體中文軟件,必須支持GB 18030編碼。爲了使得咱們這個全新的Linux系統符合我國標準,我添加了對GB 18030的支持。不過咱們最常使用的仍是UTF-8,因此這個也被添加進去了。
目前國內用得最多:gbk/gb2312 ,gb2312 包含於gbk ,Gbk 是 gb18030 的子集,gbk 包含中日韓 通殺亞洲語言
utf8 utf8mb4
centos mysql 實戰 第六節課 字符集 多字節 三碼統一 繼承 常見的字符集有哪些呢 存儲長度 看看國內大廠都在用什麼字符集 字符集配置 字符集轉換 怎麼避免亂碼
http://www.cnblogs.com/MYSQLZOUQI/p/5406343.html
而後是建立/etc/nsswitch.conf和/etc/ld.so.conf文件。nsswitch.conf文件確保glibc在網絡環境下可以良好的工做。ld.so.conf文件用來配置共享庫的搜索路徑。默認狀況下,是在/lib、/lib6四、/usr/lib和/usr/lib64這幾個目錄下搜索,可是若是想添加新的搜索路徑,必須修改這個文件。如今使用以下命令編輯它們:
# cat>/etc/nsswitch.conf<<「EOF」 passwd:files group:files shadow:files hosts:files dns networks:files protocols:files services:files ethers:files rpc:files EOF # cat>/etc/ld.so.conf<<「EOF」 /usr/local/lib /usr/local/lib64 /opt/lib /opt/lib64 EOF
最後是修改時區。經過相似這樣的命令:
# cp-V--remove-destination/usr/share/zoneinfo/<xxxx>/etc/localtime
命令中的<xxxx>內容,可經過tzselect命令確認。
16.3.3 調整工具鏈
當前咱們的工具鏈所生成的程序還不能使用新的glibc,因此須要作一番調整。爲何咱們選擇在安裝並配置好glibc以後來調整工具鏈呢?首先要感謝一下glibc的徹底生活自理能力,這使得用目前的工具鏈來編譯的glibc不會有任何依賴問題,也使得將工具鏈中的「四角戀」轉移到目標系統中成爲比較容易進行的事情。
還記得最後一次在工具鏈中生成binutils時,留下來的那個小尾巴嗎?就是那個ld-new!如今該它登場了。執行以下命令:
# my-v/toolchain/bin/{ld,ld-old} # my-v/toolchain/$(gcc-dumpmachine)/bin/{ld,ld-old} # my-v/toolchain/bin/{ld-new,ld} # In-sv/toolchain/bin/ld/toolchain/$(gcc-dumpmachine)/bin/ld
真是「明修棧道,暗渡陳倉」啊!而後還要修改specs文件,只不過此次沒有編輯器能夠用了,用命令吧:
# gcc-dumpspecs|sed-e’s@/toolchain@@g’\ -e’/\*startfile_prefix_spec:/{n;s@.*@/usr/lib64/@}’\ -e’/\*cpp:/{n;s@$@-isystem/usr/include@}’>\ ‘dirname$(gcc—print-libgcc-file-name)‘/specs
此次修改的地方稍微有些不一樣,就是更改startfile_prefix_spec的配置信息。
修改完畢後,執行一下測試,查看一下相關的依賴都已經轉移到了新的系統上面來。若是沒有什麼問題。就能夠繼續了。
16.3.4 安裝binutils
這裏要比製做工具鏈時要簡單不少了。執行下列命令:
#../binutils-2.22/configure--prefix=/usr—enable-shared # make tooldir=/usr #make-k check # make tooldir=/usr install # cp-v../binutils-2.22/include/libiberty.h/usr/include
這一系列命令仍是很是好理解的。可能有些疑惑的是make的參數「tooldir=/usr」。可是認真看本書的都知道這是Makefile的變量。tooldir這個變量的值在Makefile中是$(exec_prefix)/$(target_alias)。在這個場景中,就是/usr/x86_64-unknow-linux-gnu。咱們確定不但願咱們的目標系統的/usr目錄裏有特殊的子目錄。因此就利用命令行方式將它覆蓋掉。
爲了保證咱們安裝的binutils沒有問題,在安裝以前必定要進行測試。若是在這個過程當中發現了太多的錯誤,必定是工具鏈出現了問題。最悲催的狀況就是須要從新創建工具鏈。
libiberty.h這個頭文件被不少軟件使用。可是它不會被安裝,因此須要手動將它複製到合適的位置。
16.3.5 安裝gcc
此次咱們編譯gee時,要與在建立工具鏈時有很大不一樣了。
首先,gmp、mpfr和mpc這三個軟件的源碼不須要與gcc的源碼合併了,而是直接在目標系統中安裝它們。
其次,在編譯gcc以前,還要先安裝zlib。若是不這麼作,gcc會用本身的實現。但是它本身的實現並不會安裝到系統中。然而,有好多軟件須要使用zlib提供功能。那麼zlib就必須安裝。爲了保持目標系統的一致性,全部軟件都統一使用一份zlib,那麼就要求gcc使用由系統提供的zlib來代替它本身的實現。
最後,還要禁止gcc安裝它本身的libiberty.a,由於在安裝binutils的時候已經有了。
咱們最早開始安裝zlib。命令以下:
# tar vxf zlib-1.2.5.tar.bz2 # cd zlib-1.2.5 # sed-i‘s/ifdef_LARGEFILE64_SOURCE/ifndef_LARGEFILE64_SOURCE/’zlib.h # CFLAGS=‘-mstackrealign-fPIC-03’./configure--prefix=/usr # make # make check # make install
須要修改zlib.h文件是由於有一處筆誤,須要將它修正過來。給configure程序提供CFLAGS變量,是由於默認的優化選項會致使運行時錯誤。
而後是安裝gmp。命令以下:
# tar vxf gmp-5.0.2 # cd gmp-5.0.2 # sed-i‘s/np+dn,qn/&-dn/’mpn/generic/dcpil_bdiv_q.c #./configure--prefix=/usr--enable--cxx--enable-mpbsd # make # make check 2>&1|tee gmp-check-log # make install # mkdir-v/usr/share/doc/gmp-5.0.2 # cp-v doc/{isa_abi_headache,configuration}doc/*.html\ /usr/share/doc/gmp-5.0.2
這裏使用sed的是修正測試時的一個bug。因爲gmP不會安裝它的幫助文檔,因此咱們手工複製一下。
而後是安裝mpfr。命令以下:
# tar vxf mpfr-3.1.0 # cd mpfr-3.1.0 #./configure--prefix=/usr-enable—thread-safe\ --docdir=/usr/share/doc/mpfr-3.1.0 # make # make check # make install # make html # make install-html
最後是安裝mpc。命令以下:
# tar vxf mpc-0.9.tar.bz2 # cd mpc-0.9 ./configure--prefix=/usr # make # make check # make install
Gmp、mpfr和mpc三者之間須要按照這個順序進行安裝,由於它們有這個依賴關係。待它們都安裝好後。就能夠安裝gcc了。命令以下:
# tar vxf gcc-4.6.2.tar.bz2 # cd gcc-4.6.2 # sed-i‘s/install_to_$(INSTALL_DEST)//’libiberty/Makefile.in # sed-i‘s/ΛT_CFLAGS=$/&-fomit-frame-pointer/’gcc/Makefile.in # sed-i‘s@\./fixinc\.sh@-c true@’gcc/Makefile.in # mkdir../gcc-build # cd../gcc-build # ../gcc-4.6.1/configure--prefix=/usr --libexecdir=/usr/lib—enable-shared\ --enable-threads=posix—enable-__cxa_atexit\ --enable-clocale=gnu—enable-languages=c,c++\ --disable-multilib-disable-bootstrap--with-system-zlib # make-j # make-k check # make install # In-sv../usr/bin/cpp/lib64 # In-sv gcc/usr/bin/cc
這些命令中:第一個sed禁止gcc生成本身的libiberty.a;第二個sed強制添加-fomit-frame-pointer優化;第三個是禁用fixinclude腳本:configure的--with-system-zlib這個參數使得gcc使用系統提供的zlib,也就是咱們最開始安裝的zlib;最後面建立的兩個符號鏈接是爲了保持系統的兼容性,由於不少軟件會用它們。
當gcc安裝完畢後,緊密的「四角戀」就在目標系統中創建起來了。這個時候咱們就能夠利用目標系統的編譯器、鏈接器和程序庫編譯並安裝其餘的基礎設施了。
順便說一句,安裝完畢後,不要忘記測試一下「四角戀」是否真的已經在目標系統中創建起來了。方法與創建工具鏈時使用的是相同的。
16.3.6 安裝其餘基礎設施
做爲一個可以獨立運行的Linux系統,還須要以下的軟件包:
表16-2
軟件包 |
說明 |
File-5.09 |
檢測文件類型的工具 file命令 |
Sed-4.2 |
這是一個流式文本編輯器。用途很是多,主要用在shell腳本修改文本文件的場景 |
Bzip2-1.0.6 |
一個基於bzip2算法的壓縮解壓縮工具。全部以.bz2結尾的文件都使用它來解壓縮 |
Ncurses-5.9 |
很是著名的字符界面庫。能夠在字符界面實現窗口的繪製等 |
Util-linux-2.20.1 |
一個Linux工具集,其中包括處理文件系統、控制檯、磁盤分區和信息的工具。Mount、fdisk、mkswap等工具出自這個軟件包 |
Psmisc-22.14 |
進程管理工具包,fuser、killall、pstree等工具出自這個軟件包 |
E2fsprogs-1.42 |
ext2文件系統工具箱,好比mkfs.ext2、fsck.ext2等。同一系列的ext3、ext4文件系統的管理工具亦出自這個軟件包 |
Coreutils-8.14 |
Linux系統的核心工具包。好比rm、mkdir、is等都出自這個軟件包 |
Iana-Etc-2.30 |
提供兩個文件/etc/protocols和/etc/services。這兩個文件提供了網絡服務和協議的配置數據 |
軟件包 |
說明 |
M4-1.4.16 |
這是一個宏處理器,並內置了不少宏。是不少自動化工具的基礎設施 |
Bison-2.5 |
詞法分析程序生成器,就是GNU版的yacc, Bison是Inception服務所依賴的包之一
|
Procps-3.2.8 |
利用/proc特種文件系統的,提供進程管理的程序包。著名的ps、kill,free,sysctl等命令就出自這個軟件包 |
Grep-2.10 |
很是著名的基於正則表達式的文本搜索程序 |
Readline-6.2 |
提供命令行編輯和歷史記錄功能的庫集合,pgsql的客戶端psql須要上下翻頁和歷史命令功能依靠的是readline這個庫 |
Bash-4.2 |
Linux下最爲流行的shell,也是Linux的標準shell。全部Linux系統都應該提供 |
Libtool-2.4.2 |
GNU通用庫支持腳本,將使用動態庫的複雜性隱藏在統一的、可移植的接口中 |
GDBM-1.10 |
GNU數據庫管理器。這是一個單文件的Key-Value數據庫 |
Inetutils-1.8 |
包含基礎網絡程序的程序包。著名的ping和telnet就出自這個軟件包 |
Perl-5.14.2 |
很是經典的Perl語言 |
Autoconf-2.68 |
Autotools工具之一。能生成用於自動配置源代碼的shell腳本。咱們一直在使用的configure程序就是它的「傑做」 |
Automake-1.11.2 |
與Autoconf配合使用,用於產生Makefile文件 |
Diffutils-3.2 |
文件比對工具,常常用於生成補丁文件 |
Gawk-4.0.0 |
Awk語言,編寫shell腳本時常用。用於處理文本文件 |
Findutils-4.4.2 |
就是著名的find工具 |
Flex-2.5.35 |
一個詞法分析程序生成器。是GNU版的lex, Bison是Inception服務所依賴的包之一
|
Gettext-0.18.1.1 |
系統的國際化和本地化的工具。Linux多國語言支持就靠它了 |
Groff_1.21 |
包含一些處理和格式化文本的程序 |
GRUB-1.99 |
咱們要使用的多系統引導加載程序 |
Gzip-1.4 |
基於gzip算法的壓縮和解壓縮工具。全部以.gz結尾的文件須要使用它來解壓縮 |
IPRoute2-3.1.0 |
包含了基本的和高級的基於IPv4網絡的程序。好比ifcfg、rtmon等工具就出自這個軟件包 |
Kbd-1.15.2 |
鍵盤映射表和鍵盤工具 |
Less-444 |
文本查看器less less命令 |
Make-3.82 |
很是著名的make工具 |
Xz-5.0.3 |
這是一個基於LZMA算法的壓縮與解壓縮工具。有很高的壓縮比。以.xz結尾的文件使用它來解壓縮 |
Man-DB-2.6.0.2 |
Linux的在線手冊工具包。著名的man就來自這裏 |
軟件包 |
說明 |
Module-Init-Tools-3.16 |
Linux內核可加載模塊管理工具 |
Patch-2.6.1 |
很是著名的打補丁工具,它的補丁文件來源於diff工具 |
Shadow-4.1.4.3 |
安全方式下處理密碼的程序包。著名的useradd、usermod、passwd等命令就出自這裏。 |
Sysklogd-1.5 |
系統日誌守護進程 |
Sysvinit-2.88dsf |
控制系統啓動、運行和關閉的程序包。著名的init進程就來自這裏 |
Tar-1.26 |
Tar包管理程序 |
Texinfo-4.13a |
一整套info文檔工具。Linux除了man幫助,還有更爲詳細的info文檔 |
Udev-173 |
利用/sys特種文件系統,在用戶空間實現設備管理的軟件包 |
Vim-7.3 |
著名的文本編輯器,屬於Linux的默認編輯器,不少工具會調用它做爲編輯器使用,好比visudo、crontab -e |
這些軟件構成了一個最小的Linux系統運行環境。可能它們之間會有一些依賴關係。可是按照表16-2中給出的順序進行編譯安裝沒有發現任何問題。
16.3.7 系統啓動腳本
此時此刻系統的軟件環境已經準備好了,可是這些軟件該如何協調,乃至這些軟件與系統的硬件如何協調使用仍是一個很大的問題。解決這個問題就要請出系統啓動腳本,見表16-3。
表16-3
腳本 |
說明 |
checkfs |
在系統啓動階段,對即將要掛接的文件系統進行完整性檢查。日誌文件系統和基於網絡的文件系統除外 |
cleanfs |
在系統重啓或關閉階段,刪除不須要保存的文件。 例如在/var/run/和/var/lock/目錄下的文件; 從新建立/var/run/utmp文件並刪除可能存在的/etc/nologin、/fastboot、/forcefsck文件 |
console |
爲指定的鍵盤佈局讀入正確的鍵盤映射表,並設置屏幕字體 |
consolelog |
設置內核日誌級別來控制信息到達控制檯 |
functions |
包含在不一樣腳本中共用的一些函數,例如錯誤和狀態檢查函數 |
halt |
關閉系統 |
ifdown |
協助network腳本中止網絡設備 |
腳本 |
說明 |
ifup |
協助network腳本啓動網絡設備 |
localnet |
設置系統主機名和本地迴環(loopback)設備 |
modules |
加載/etc/sysconfig/modules目錄列出的內核模塊,使用的參數也會在這個目錄給出 |
mountfs |
系統啓動階段,掛接全部文件系統,有noauto標記或者基於網絡的文件系統除外 |
mountkernfs |
系統啓動階段,加載虛擬內核文件系統,好比proc |
network |
配置網絡接口,如網卡,並設置默認網關(若是可用) |
rc |
提供命令行編輯和歷史記錄功能的庫集合 |
reboot |
從新啓動系統 |
sendsignals |
在系統重啓或關閉系統以前,確保每個進程都已經終止了 |
setclock |
若是硬件時鐘沒有設置爲UTC時間,將內核時鐘重置爲本地時間 |
static |
提供爲網絡接口指派靜態IP地址的功能 |
swap |
啓用或禁用交換文件和交換分區 |
sysctl |
若是/etc/sysctl.conf存在,將該文件的系統配置數據加載到運行的內核中 |
sysklogd |
啓動或中止系統和內核日誌守護進程 |
template |
爲其餘守護進程建立自定義啓動腳本的模板 |
udev |
啓動udev並在/dev目錄建立設備節點 |
udev_retry |
若是須要,重試失敗的udev消息,並從/dev/.udev拷貝通用的規則文件到/etc/udev/rules.d |
須要提醒你們注意的是,表16-3只是在大致上給出了一個Linux系統在啓動或關閉過程可能須要執行或必須執行的操做。這貌似是在說「車軸轆話」。之因此這樣,是由於LSB只規定了Linux的啓動或關閉的方式,並無規定在啓動或關閉的過程都要作些什麼。並且基於不一樣目的的Linux系統,在啓動或關閉階段所要執行的操做也會有很大差異,因此這裏是不能給出明確答案的。要想讓本身的系統能很快運行起來,最好的一個辦法就是複製宿主系統中的那些啓動腳本。至於它們的工做原理,本書在前面的章節已經講過了。
16.3.8 結束語
通過這一階段,咱們就具有了一個Linux系統可運行的基本環境。不過到目前爲止,咱們最爲關鍵的「人物」尚未登場。那就是Linux內核。只有具有了內核,一個操做系統才能真正地工做起來。稍微休息一下,咱們接下來就開始打造Linux內核。
16.4 定製Linux內核
通過這麼一系列的折騰,終於開始內核的編譯工做了。
Linux內核是很是開放滴,因此每個Linux系統均可以有一個不一樣的內核。這就比如咱們人類,每一個人都有屬於本身的心,是善、是惡、是美、是醜,那些都只是別人的標準。跟隨着你的心,走你本身的路,只要可以感到快樂就足夠了。固然,你的快樂不能創建在別人的痛苦之上,畢竟你不是在獨行。生命中老是會有一個他/她陪伴着你。無論他/她是近、是遠、是離、是合……
不禁地開始抒情起來。咱們仍是回到正題。說說Linux的內核。編譯Linux內核實際上也是定製Linux內核。這被不少人看來是一件很是神祕的事情。其實Linux內核的開發者們已經作了不少工做,幫助咱們可以輕鬆愉悅地完成這個過程。其實比較難的就是取捨。因此不少時候仍是須要英明決斷一下的。那就跟着你的心,決定Linux的「心」好了。
16.4.1 內核的make參數
Linux內核的定製、編譯乃至安裝都是經過make工具來完成的。本書已經給你們灌輸過了,經過Makefile的參數能夠決定make作什麼。那麼咱們就先看看Linux內核都提供了哪些Makafile參數。
● mrproper
這個參數在以前已經見到過了。它的做用是讓Linux內核的源代碼乾乾淨淨的。之因此須要作這個操做,是由於沒法肯定下載的源代碼是否有保留的目標文件和一些相關的配置文件存在。爲了保證可以徹頭徹尾地對內核進行定製,就須要將那些目標文件和配置文件清理乾淨。須要注意的是,這個參數會將你之前的配置信息也刪除掉。因此這個參數通常只應用在對某個版本內核的首次定製和編譯的時候。其餘狀況下請使用clean參數。由於這個參數僅要求刪除一些相似目標文件,而不會刪除配置信息。這個很重要,千萬不要弄亂。畢竟配置好一個版本的內核是比較辛苦的一個過程。
● menuconfig
這個參數是定製Linux內核時最經常使用的參數。它在文本模式下提供了一個基於窗口交互的配置界面。這個功能須要ncurses庫的支持(以前咱們已經提供過了)。另一個經常使用的定製內核參數是oldconfig。它是利用已存在的老版本內核的配置信息做爲預設值,僅將新版本內核的新功能列出讓定製者選擇的一種方式,這能夠極大簡化內核的定製過程。與之同類的參數還有xconfig和gconfig,這個兩個參數都提供了一個基於圖形交互的配置界面,前者基於QT,後者基於Gtk。最古老也沒人使用的是config參數。將內核的配置項一條一條地列出,選錯了只能重頭再來。
● bzlmage
最經常使用的編譯Linux內核參數。給定這個參數後,編譯出來的內核鏡像是壓縮過的。具體使用什麼壓縮算法在定製階段指定。比較不經常使用或根本不用的是vmlinux,編譯出來的內核鏡像未經壓縮。只有對目標硬件環境很是瞭解,對Linux內核很是瞭解,且須要極快的啓動速度時,纔會考慮使用該參數。
● modules
編譯內核可加載模塊。Linux內核只提供了這一個參數用來編譯可加載模塊,因此也沒什麼好選擇的。
● modules_install
安裝內核可加載模塊。也沒什麼好選擇的。不過你可能會聯想到參數install是用來安裝內核鏡像的。猜得不錯,可是通常不用這個參數,由於它會修改啓動記錄。絕大多數Linux發行版使用GRUB,並不但願Linux內核本身完成引導過程,因此這個參數基本不用。
上述的這些參數是定製、編譯和安裝Linux內核最爲經常使用的。若是對其餘參數感興趣,能夠使用help參數來查看幫助信息。我在這裏不作過多的介紹了。
16.4.2 定製界面
因爲咱們只提供ncurses,因此要徹底完全地定製Linux內核,只能使用menuconfig這個選項。那麼咱們就執行這個命令,看看定製界面是什麼樣的(見圖16.2所示)。
# make menuconfig
看到上面的圖示以後,會發現Linux內核的配置界面主要分爲三個部分。最上部是幫助信息;中部是設置項;下部是導航。中部和下部是主要的交互區域,從上部的幫助信息中能夠了解如何操做這兩個交互區域。這是一個相似「分層菜單」的交互界面。這是最頂層菜單。最頂層菜單的每一個設置項,都會有多級菜單的子設置項。
使用「左右」方向鍵,能夠移動下部的光標,選擇<Select>、<Exit>和<Help>按鈕;使用「上下」方向鍵,能夠移動中部的光標,選擇各個設置項;在設置項的開頭若是出現有相似「[]」或「<>」這樣的符號,代表該設置項是可選項,能夠用「空格」鍵進行選擇;若設置項的結尾處有「--->」這樣的箭頭,則表示該設置項還有若干子設置項,能夠使用「回車」鍵進一步查看子設置項。若是在設置項前面出現相似「[*]」或「<*>」這樣的符號,則表示該設置項對應的功能會直接編譯進內核鏡像:若是是「<M>」則表示該設置項對應的功能會被編譯成可加載模塊;在任什麼時候候選按下部的<Exit>按鈕,都會退出當前子設置項列表或退出配置界面。
這裏在配置內核的時候有一些小小的建議。建議只使用「上下左右方向鍵、空格、回車」這六個按鍵就能夠了。儘可能不要使用Esc,由於可能一不當心就按錯了。另外,對於整個內核功能上的選擇,我也提供一點本身的看法:
1.肯定是內核必須具有的功能,應該直接編譯到內核鏡像中。
2.不肯定是內核必須具有的,但未來可能會用到的功能,儘可能編譯成可加載模塊。
3.不知道幹什麼的功能,甚至查看help也搞不懂的功能,就保留預設值,或者將它們編譯成可加載模塊。
總之,儘可能保持內核的小而美,餘下的功能編譯成可加載模塊。若是就是本身玩玩,就不要猶豫不定,當機立斷最好。若是拿來跟別人分享,那麼就儘可能多考慮一些可擴展性,不過這也是最難抉擇的。只有經驗才一能賦予你足夠強大的能力。
若是想進一步瞭解每一個設置項所對應的功能,那麼能夠選按<Help>按鈕查看相關的幫助信息。若是以爲幫助信息沒法說明問題,那麼最好的辦法是問谷哥。正所謂:「內事問百度,外事問谷哥。」這裏百度能幫上的忙有限。
16.4.3 編譯與安裝
當內核定製完畢後,就開始進行編譯和安裝操做了。通常執行下列命令:
# make bzImage # make modules_install # cp-v arch/x86/boot/bzlmage/boot/vmlinuz-3.1.6-mgc3.x86_64 # cp-v.config/boot/config-3.1.6 #cp-v System.map/boot/System.map-3.1.6 # install-d/usr/share/doc/linux-3.1.6 # cp-r Documentation/*/usr/share/doc/linux-3.1.6 # install-v-m755-d/etc/modprobe.d
這裏須要說明一下的是System.map文件和/etc/modprobe.d這個目錄。System.map文件是內核的符號文件。它映射了內核API中每一個函數的入口,以及正在運行內核的數據結構的地址。在調試內核問題時,它是一種極其重要的資源。/etc/modprobe.d這個目錄用於配置內核可加載模塊的加載順序。具體如何配置是根據內核自己定製的特性決定的,因此這裏再也不給出。但願瞭解的同窗能夠自行研究。
16.5 獨立運行
十月懷胎,一朝分娩。咱們滿心期待的「嬰兒」就要呱呱墜地了,咱們須要完全剪斷「臍帶」,讓它自由地呼吸在這個陌生的世界裏。
16.5.1 /etc/fstab文件
無論你信不信,/etc/fstab文件都是讓Linux系統可以獨立運行的十分重要的文件。這個文件用來肯定哪些文件系統被自動掛接。若是沒有它,Linux系統將沒法確認「根」文件系統,沒有「根」怎麼能立足呢?/etc/fstab文件不但決定了哪些文件系統被自動掛接,還決定了它們的掛接順序以及是否須要進行掛接前的監測(主要是完整性校驗)。它的內容通常相似這樣:
# file system mount-point type options dump fsck /dev/<xxx> / <fff> defaults 1 1 /dev/<yyy> swap swap pri=1 0 0 proc /proc proc defaults 0 0 sysfs /sys sysfs defaults 0 0 devpts /dev/pts devpts gid=4,mode=620 0 0 tmpfs /dev/shm tmpfs defaults 0 0
只要將你係統上的適當值替換<xxx>、<yyy>和<fff>便可,好比sdal、sda2和ext3。有關文件中六個字段的詳細介紹,能夠參考「man 5 fstab」,且本書以前也介紹過了,這裏不作複述。
16.5.2 使用GRUB配置啓動過程
GRUB幾乎成爲Linux世界的標準引導程序,目前的絕大多數Linux發行版都使用GRUB做爲引導器。也從這一點間接地證實了GRUB的強大之處。
在使用和配置GRUB的時候要注意,它使用本身的驅動器和分區命名方式。基本格式是這樣的:(hdn,m),這裏n是硬盤號,m是分區號。硬盤號從「0」開始,而分區號,對於主分區是從「1」開始,擴展分區則是從「5」開始。我還要提一句的是,當前版本的GRUB與老版本的有些差異,老版本的分區號也是從「0」開始的。將GRUB與Linux進行對應,如sda1就是(hd0,1),sdb3就是(hd1,3)。可是相對與Linux,GRUB不會將CD-ROM驅動器看成硬盤看待。因此,若是sdb是光驅,而sdc是另一塊硬盤的話,sdc在GRUB中依然是(hd1)。經過下面的命令可看一下GRUB是如何看待你的磁盤設備的:
# grub-mkdevicemap--device-ma=device.map # cat device.map
每一個人的設備不盡相同,因此我就不列出結果了,你們本身看就好了。
讓GRUB工做,就是讓它更改引導記錄,並正確配置GRUB。方法也很簡單,只要執行下面的命令:
# grub-install/dev/sda # grub-mkconfig-o/boot/grub/grub.cfg
第一個命令就是將GRUB的引導記錄寫入MBR,我將設啓動盤是第一個硬盤。第二個命令是自動生成配置文件,配置文件的路徑是/boot/grub/grub.cfg。這就能夠了。不少人還在想如何編寫GRUB的配置文件吧?其實是不用編寫,一切都是自動完成的。
這時只要從新啓動系統,就能夠選擇使用咱們剛剛編譯生成的Linux系統了。若是以前沒有什麼錯誤,確定會是一個了不得的系統的。
16.6 結束語
到此,我終於將如何從頭至尾編譯Linux系統的整個過程展示給你們了。不少人或許但願可以在本章中一步一步地操做,並在本章結束時就能擁有一個本身的Linux系統。其實這是不現實的,由於編譯這麼大的一個工程是很是耗費時間的。在個人最新的Mac Book Pro電腦上要完成這個過程大概須要7個小時左右,顯然這麼長的時間沒人會樂意花在看這種無聊的書上。所以我不得不作一個折中,只講解那些關鍵的地方,並提供編譯步驟和必備的軟件給你們,並將原理傳授給你們,但願你們讀完本章後可以理解這些步驟的做用,以便未來參考LFS獨立完成。
nsswitch.conf配置文件
http://blog.chinaunix.net/uid-20788470-id-1841614.html
今天在公司的服務器上/etc/resolves.conf文件中增長了DNS服務器IP地址, 可是發現還不解析域名, 搞的很鬱悶, 後來找到一個同事, 原來是nsswitch.conf文件的hosts項的文件:
原來的: hosts: files
修改後的: hosts: files dns #這表示對域名, 先用/etc/hosts文件解析, 解析不了再查dns
nsswitch.conf:服務搜索順序
隨着NIS和DNS的出現,查找用戶信息和系統信息就再也不是搜索本地文件這樣簡單的事情了。之前,查看/etc/passwd文件就能夠獲取用戶信息,查看/etc/hosts文件就能夠找到系統地址信息,而如今使用多種途徑來查找這類信息。文件/etc/nsswitch.conf(name service switch configuration,名字服務切換配置)規定經過哪些途徑以及按照什麼順序經過這些途徑來查找特定類型的信息。還能夠指定若某個方法奏效抑或失效系統將採起什麼動做。
格式
文件nsswitch.conf中的每一行配置都指明瞭如何搜索信息,好比用戶的口令。nsswitch.conf每行配置的格式以下:
info: method [[action]] [method [[action]]...]
其中,info指定該行所描述的信息的類型,method爲用來查找該信息的方法,action是對前面的method的返回狀態的響應。action要放在方括號裏面。
nsswitch.conf的工做原理
當須要提供nsswitch.conf文件所描述的信息的時候,系統將檢查含有適當info字段的配置行。它按照從左向右的順序開始執行配置行中指定的方法。 在默認狀況下,若是找到指望的信息,系統將中止搜索。若是沒有指定action,那麼當某個方法未能返回結果時,系統就會嘗試下一個動做。有可能搜索結束都沒有找到想要的信息。
1. 信息
nsswitch.conf文件一般控制着用戶(在passwd中)、口令(在shadow中)、主機IP地址和組信息的搜索。 下面的列表描述了nsswitch.conf文件控制搜索的大多數信息(前面所討論的配置行格式中的info)的類型。
automount 自動掛載(/etc/auto.master和/etc/auto.misc)
bootparams 無盤引導選項和其餘引導選項(參見bootparam的手冊頁)
ethers MAC地址
group 用戶所在組(/etc/group)
hosts 系統信息(/etc/hosts)
networks 網絡信息(/etc/networks)
passwd 用戶信息(/etc/passwd)
protocols 協議信息(/etc/protocols)
publickey 用於安全模式下運行的NFS
rpc RPC名稱和編號(/etc/rpc)
services 服務信息(/etc/services)
shadow 映射口令信息(/etc/shadow)
2. 方法
下面列出了nsswitch.conf配置文件控制搜索的信息類型(前面所討論的配置行格式中的method)。對於每一種信息類型,均可以指定下面的一種或者多種方法:
files 搜索本地文件,如/etc/passwd和/etc/hosts
nis 搜索NIS數據庫,nis還有一個別名,即yp
dns 查詢DNS(只查詢主機)
compat passwd、group和shadow文件中的±語法(參見本節後面的相關內容)
3. 搜索順序
兩個或者更多方法所提供的信息可能會重疊。舉例來講,files和nis可能都提供同一個用戶的口令信息。若是出現信息重疊現象,就須要考慮將哪種方法做爲權威方法(優先考慮),並將該方法放在方法列表中靠左的位置上。
默認nsswitch.conf文件列出的方法並無動做項,並假設沒有信息重疊(正常狀況)。在這種狀況下,搜索順序可有可無:當一種方法失敗以後,系統就會嘗試下一種方法,只是時間上受到一點損失。若是在方法之間設置了動做,或者重疊的項的內容不一樣,那麼搜索順序就變得重要起來。
下面幾行取自nsswitch.conf文件,第一行讓系統在/etc/passwd文件中搜索口令信息,若是失敗的話,就使用NIS來查找信息。若是正在查找的用戶同時出如今這兩個地方,就會使用本地文件中的信息,所以它就是權威信息。第二行使用NIS搜索;若是失敗的話,就搜索/etc/hosts文件;若是再次失敗的話,覈對DNS以找出主機信息。
4. 動做項
在每一個方法後面均可以選擇跟一個動做項,用來指定若是因爲某種緣由該方法成功抑或失敗須要作些什麼。動做項的格式以下:
[[!]STATUS=action]
其中,開頭和末尾的方括號屬於格式的一部分,並非用來指出括號中的內容是可選的。STATUS(按照約定使用大寫字母,但自己並不區分大小寫)是待測試的狀態,action是若是STATUS匹配前面的方法所返回的狀態將要執行的動做。開頭的感嘆號(!)是可選的,其做用是將狀態取反。
STATUS
STATUS的取值以下。
l NOTFOUND——方法已經執行,可是並無找到待搜索的值。默認的動做是continue。
l SUCCESS——方法已經執行,而且已經找到待搜索的值,沒有返回錯誤。默認動做是return。
l UNAVAIL——方法失敗,緣由是永久不可用。舉例來講,所需的文件不可訪問或者所需的服務器可能停機。默認的動做是continue。
l TRYAGAIN——方法失敗,緣由是臨時不可用。舉例來講,某個文件被鎖定,或者某臺服務器超載。默認動做是continue。
action
action的取值以下:
l return——返回到調用例程,帶有返回值,或者不帶返回值。
l continue——繼續執行下一個方法。任何返回值都會被下一個方法找到的值覆蓋。
示例
舉例來講,下面這行取自nsswitch.conf文件,它的做用是讓系統首先使用DNS來搜索給定主機的IP地址。DNS方法後面的動做項是測試該方法所返回的狀態是否爲「非(!)UNAVAIL」。
若是DNS方法沒有返回UNAVAIL(!UNAVAIL),也就是說DNS返回SUCCESS、NOTFOUND或者TRYAGAIN,那麼系統就會執行與該STATUS相關的動做(return)。其結果就是,只有在DNS服務器不可用的狀況下才會使用後面的方法(files)。若是DNS服務器並非不可用(兩次否認以後就是「可用」),那麼搜索返回域名或者報告未找到域名。只有當服務器不可用的時候,搜索纔會使用files方法(檢查本地的/etc/hosts文件)。
5. compat方法:passwd、group和shadow文件中的「±」
能夠在/etc/passwd、/etc/group和/etc/shadow文件中放入一些特殊的代碼,(若是在nsswitch.conf文件中指定compat方法的話)讓系統將本地文件和NIS映射表中的項進行合併和修改。
在這些文件中,若是在行首出現加號(+),就表示添加NIS信息;若是出現減號(-),就表示刪除信息。舉例來講,要想使用passwd文件中的這些代碼,能夠在nsswitch.conf文件中指定passwd: compat。而後系統就會按照順序搜尋passwd文件,當它遇到以+或者-開頭的行時,就會添加或者刪除適當的NIS項。
雖然能夠在passwd文件的末尾放置加號,在nsswitch.conf文件中指定passwd: compat,以搜索本地的passwd文件,而後再搜尋NIS映射表,可是更高效的一種方法是在nsswitch.conf文件中添加passwd: file nis而不修改passwd文件。
cat /etc/nsswitch.conf # # /etc/nsswitch.conf # # An example Name Service Switch config file. This file should be # sorted with the most-used services at the beginning. # # The entry '[NOTFOUND=return]' means that the search for an # entry should stop if the search in the previous entry turned # up nothing. Note that if the search failed due to some other reason # (like no NIS server responding) then the search continues with the # next entry. # # Valid entries include: # # nisplus Use NIS+ (NIS version 3) # nis Use NIS (NIS version 2), also called YP # dns Use DNS (Domain Name Service) # files Use the local files # db Use the local database (.db) files # compat Use NIS on compat mode # hesiod Use Hesiod for user lookups # [NOTFOUND=return] Stop searching if not found so far # # To use db, put the "db" in front of "files" for entries you want to be # looked up first in the databases # # Example: #passwd: db files nisplus nis #shadow: db files nisplus nis #group: db files nisplus nis passwd: files shadow: files group: files #hosts: db files nisplus nis dns hosts: files dns # Example - obey only what nisplus tells us... #services: nisplus [NOTFOUND=return] files #networks: nisplus [NOTFOUND=return] files #protocols: nisplus [NOTFOUND=return] files #rpc: nisplus [NOTFOUND=return] files #ethers: nisplus [NOTFOUND=return] files #netmasks: nisplus [NOTFOUND=return] files bootparams: nisplus [NOTFOUND=return] files ethers: files netmasks: files networks: files protocols: files rpc: files services: files netgroup: nisplus publickey: nisplus automount: files nisplus aliases: files nisplus
cat /etc/protocols # /etc/protocols: # $Id: protocols,v 1.9 2009/09/29 15:11:55 ovasik Exp $ # # Internet (IP) protocols # # from: @(#)protocols 5.1 (Berkeley) 4/17/89 # # Updated for NetBSD based on RFC 1340, Assigned Numbers (July 1992). # Last IANA update included dated 2009-06-18 # # See also http://www.iana.org/assignments/protocol-numbers ip 0 IP # internet protocol, pseudo protocol number hopopt 0 HOPOPT # hop-by-hop options for ipv6 icmp 1 ICMP # internet control message protocol igmp 2 IGMP # internet group management protocol ggp 3 GGP # gateway-gateway protocol ipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'') st 5 ST # ST datagram mode tcp 6 TCP # transmission control protocol cbt 7 CBT # CBT, Tony Ballardie <A.Ballardie@cs.ucl.ac.uk> egp 8 EGP # exterior gateway protocol igp 9 IGP # any private interior gateway (Cisco: for IGRP) bbn-rcc 10 BBN-RCC-MON # BBN RCC Monitoring nvp 11 NVP-II # Network Voice Protocol pup 12 PUP # PARC universal packet protocol argus 13 ARGUS # ARGUS emcon 14 EMCON # EMCON xnet 15 XNET # Cross Net Debugger chaos 16 CHAOS # Chaos udp 17 UDP # user datagram protocol mux 18 MUX # Multiplexing protocol dcn 19 DCN-MEAS # DCN Measurement Subsystems hmp 20 HMP # host monitoring protocol prm 21 PRM # packet radio measurement protocol xns-idp 22 XNS-IDP # Xerox NS IDP trunk-1 23 TRUNK-1 # Trunk-1 trunk-2 24 TRUNK-2 # Trunk-2 leaf-1 25 LEAF-1 # Leaf-1 leaf-2 26 LEAF-2 # Leaf-2 rdp 27 RDP # "reliable datagram" protocol irtp 28 IRTP # Internet Reliable Transaction Protocol iso-tp4 29 ISO-TP4 # ISO Transport Protocol Class 4 netblt 30 NETBLT # Bulk Data Transfer Protocol mfe-nsp 31 MFE-NSP # MFE Network Services Protocol merit-inp 32 MERIT-INP # MERIT Internodal Protocol dccp 33 DCCP # Datagram Congestion Control Protocol 3pc 34 3PC # Third Party Connect Protocol idpr 35 IDPR # Inter-Domain Policy Routing Protocol xtp 36 XTP # Xpress Tranfer Protocol ddp 37 DDP # Datagram Delivery Protocol idpr-cmtp 38 IDPR-CMTP # IDPR Control Message Transport Proto tp++ 39 TP++ # TP++ Transport Protocol il 40 IL # IL Transport Protocol ipv6 41 IPv6 # IPv6 sdrp 42 SDRP # Source Demand Routing Protocol ipv6-route 43 IPv6-Route # Routing Header for IPv6 ipv6-frag 44 IPv6-Frag # Fragment Header for IPv6 idrp 45 IDRP # Inter-Domain Routing Protocol rsvp 46 RSVP # Resource ReSerVation Protocol gre 47 GRE # Generic Routing Encapsulation dsr 48 DSR # Dynamic Source Routing Protocol bna 49 BNA # BNA esp 50 ESP # Encap Security Payload ipv6-crypt 50 IPv6-Crypt # Encryption Header for IPv6 (not in official list) ah 51 AH # Authentication Header ipv6-auth 51 IPv6-Auth # Authentication Header for IPv6 (not in official list) i-nlsp 52 I-NLSP # Integrated Net Layer Security TUBA swipe 53 SWIPE # IP with Encryption narp 54 NARP # NBMA Address Resolution Protocol mobile 55 MOBILE # IP Mobility tlsp 56 TLSP # Transport Layer Security Protocol skip 57 SKIP # SKIP ipv6-icmp 58 IPv6-ICMP # ICMP for IPv6 ipv6-nonxt 59 IPv6-NoNxt # No Next Header for IPv6 ipv6-opts 60 IPv6-Opts # Destination Options for IPv6 # 61 # any host internal protocol cftp 62 CFTP # CFTP # 63 # any local network sat-expak 64 SAT-EXPAK # SATNET and Backroom EXPAK kryptolan 65 KRYPTOLAN # Kryptolan rvd 66 RVD # MIT Remote Virtual Disk Protocol ippc 67 IPPC # Internet Pluribus Packet Core # 68 # any distributed file system sat-mon 69 SAT-MON # SATNET Monitoring visa 70 VISA # VISA Protocol ipcv 71 IPCV # Internet Packet Core Utility cpnx 72 CPNX # Computer Protocol Network Executive cphb 73 CPHB # Computer Protocol Heart Beat wsn 74 WSN # Wang Span Network pvp 75 PVP # Packet Video Protocol br-sat-mon 76 BR-SAT-MON # Backroom SATNET Monitoring sun-nd 77 SUN-ND # SUN ND PROTOCOL-Temporary wb-mon 78 WB-MON # WIDEBAND Monitoring wb-expak 79 WB-EXPAK # WIDEBAND EXPAK iso-ip 80 ISO-IP # ISO Internet Protocol vmtp 81 VMTP # Versatile Message Transport secure-vmtp 82 SECURE-VMTP # SECURE-VMTP vines 83 VINES # VINES ttp 84 TTP # TTP nsfnet-igp 85 NSFNET-IGP # NSFNET-IGP dgp 86 DGP # Dissimilar Gateway Protocol tcf 87 TCF # TCF eigrp 88 EIGRP # Enhanced Interior Routing Protocol (Cisco) ospf 89 OSPFIGP # Open Shortest Path First IGP sprite-rpc 90 Sprite-RPC # Sprite RPC Protocol larp 91 LARP # Locus Address Resolution Protocol mtp 92 MTP # Multicast Transport Protocol ax.25 93 AX.25 # AX.25 Frames ipip 94 IPIP # Yet Another IP encapsulation micp 95 MICP # Mobile Internetworking Control Pro. scc-sp 96 SCC-SP # Semaphore Communications Sec. Pro. etherip 97 ETHERIP # Ethernet-within-IP Encapsulation encap 98 ENCAP # Yet Another IP encapsulation # 99 # any private encryption scheme gmtp 100 GMTP # GMTP ifmp 101 IFMP # Ipsilon Flow Management Protocol pnni 102 PNNI # PNNI over IP pim 103 PIM # Protocol Independent Multicast aris 104 ARIS # ARIS scps 105 SCPS # SCPS qnx 106 QNX # QNX a/n 107 A/N # Active Networks ipcomp 108 IPComp # IP Payload Compression Protocol snp 109 SNP # Sitara Networks Protocol compaq-peer 110 Compaq-Peer # Compaq Peer Protocol ipx-in-ip 111 IPX-in-IP # IPX in IP vrrp 112 VRRP # Virtual Router Redundancy Protocol pgm 113 PGM # PGM Reliable Transport Protocol # 114 # any 0-hop protocol l2tp 115 L2TP # Layer Two Tunneling Protocol ddx 116 DDX # D-II Data Exchange iatp 117 IATP # Interactive Agent Transfer Protocol stp 118 STP # Schedule Transfer srp 119 SRP # SpectraLink Radio Protocol uti 120 UTI # UTI smp 121 SMP # Simple Message Protocol sm 122 SM # SM ptp 123 PTP # Performance Transparency Protocol isis 124 ISIS # ISIS over IPv4 fire 125 FIRE crtp 126 CRTP # Combat Radio Transport Protocol crdup 127 CRUDP # Combat Radio User Datagram sscopmce 128 SSCOPMCE iplt 129 IPLT sps 130 SPS # Secure Packet Shield pipe 131 PIPE # Private IP Encapsulation within IP sctp 132 SCTP # Stream Control Transmission Protocol fc 133 FC # Fibre Channel rsvp-e2e-ignore 134 RSVP-E2E-IGNORE # 135 # Mobility Header udplite 136 UDPLite mpls-in-ip 137 MPLS-in-IP manet 138 manet # MANET Protocols [RFC5498] hip 139 HIP # Host Identity Protocol shim6 140 Shim6 #Shim6 Protocol [RFC5533] # 141-252 Unassigned [IANA] # 253 Use for experimentation and testing [RFC3692] # 254 Use for experimentation and testing [RFC3692] # 255 Reserved [IANA]
cat /boot/grub/grub.conf # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You have a /boot partition. This means that # all kernel and initrd paths are relative to /boot/, eg. # root (hd0,0) # kernel /vmlinuz-version ro root=/dev/sda2 # initrd /initrd-[generic-]version.img #boot=/dev/sda default=0 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu title CentOS 6 (2.6.32-504.el6.x86_64) root (hd0,0) kernel /vmlinuz-2.6.32-504.el6.x86_64 ro root=UUID=030f1baf-3cea-4c9a-838a-a45eb345e91b rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet initrd /initramfs-2.6.32-504.el6.x86_64.img
rpm -qa|grep grub
grub-0.97-93.el6.x86_64 舊版本的grub
/var/run/utmp 當前登陸的用戶
strings /var/run/utmp
reboot
2.6.32-504.el6.x86_64
runlevel
2.6.32-504.el6.x86_64
tty1
root
tty3
LOGIN
tty2
LOGIN
tty6
LOGIN
tty5
LOGIN
tty4
LOGIN
pts/0
ts/0root
192.168.1.106
pts/1
/var/log/wtmp 全部的登陸和退出
strings /var/log/wtmp
reboot
2.6.32-504.el6.x86_64
9@WV
runlevel
2.6.32-504.el6.x86_64
9@WVh
tty2
LOGIN
?@WV
tty4
LOGIN
?@WV
tty5
LOGIN
?@WV
tty3
/var/log/lastlog 每一個用戶最後登陸信息
strings /var/log/lastlog
Vpts/0
192.168.1.106
Vpts/1
192.168.1.155
/var/log/btmp 錯誤的登陸嘗試
Linux就這個範兒 第8章 我是Makefile
http://www.cnblogs.com/MYSQLZOUQI/p/5208438.html
8.4.2 命令
我猜測你到如今多少對命令有了一些瞭解,可是必定還有不少疑問並無獲得解答。好比我說過,命令實際上就是shell命令。
可是Linux的shell有不少種,能叫上名字的就有如:Bash、Korn shell、C shell等幾種。那麼make執行的是那個shell的命令呢?
是否是執行make命令時所採用的shell呢(好比你採用C shell做爲默認shell)?
答案很給力,就是「/bin/sh」這個東西,別無它選。這個東西實際上就是bash,也是Linux世界中應用最爲普遍的shell,並且任何Linux發行版都會提供。
f