• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            旅途

            如果想飛得高,就該把地平線忘掉

            鳥哥的 Linux 與 ADSL 私房菜

             
            我們?cè)?Linux 是什么 一文當(dāng)中,提到了 GNU 與 GPL 還有開放源碼等咚咚,不過,前面都還沒有提到真正的開放源碼是什么的訊息!在這一章當(dāng)中,我們將藉由 Linux 操作系統(tǒng)里面的執(zhí)行文件,來理解什么是可執(zhí)行的程序,以及了解什么是編譯器。另外,與程序息息相關(guān)的函式庫(kù)(library)的信息也需要了解一番!不過, 在這個(gè)章節(jié)當(dāng)中,鳥哥并不是要您成為一個(gè)開放源碼的程序設(shè)計(jì)師,而是希望您可以了解如何將開放源碼的程序設(shè)計(jì)、加入函式庫(kù)的原理、透過編譯而成為可以執(zhí)行 的 binary file ,最后該執(zhí)行檔可被我們所使用的一連串過程!
             
            了解上面的咚咚有什么好處呢?!因?yàn)樵? Linux 的世界里面,我們常常需要自行安裝套件在自己的 Linux 系統(tǒng)上面,所以如果您有簡(jiǎn)單的程序編譯概念,那么將很容易進(jìn)行套件的安裝,甚至在發(fā)生套件編譯過程中的錯(cuò)誤時(shí),您也可以自行作一些簡(jiǎn)易的修訂呢!而最傳統(tǒng) 的套件安裝過程,自然就是由原始碼編譯而來的啰!所以,在這里我們將介紹最原始的套件管理方式:使用 Tarball 來安裝與升級(jí)管理我們的套件喔!
             
            前言
              : 什么是開放源碼、編譯器與可執(zhí)行檔
              : 什么是函式庫(kù)
              : 什么是? make 與 configure
              : 什么是 Tarball 的套件
              : 如何安裝與升級(jí)套件
            一個(gè)簡(jiǎn)單的范例
              : 印出 Hello World
              : 子程序的編譯
              : 加入連結(jié)的函式庫(kù)
              : gcc 的用法
            make 的簡(jiǎn)易用法
              : 為什么要用 make
              : make 的基本語(yǔ)法與變量
            Tarball 的管理與建議
              : 使用原始碼管理套件所需要的基礎(chǔ)套件
              : Tarball 安裝的基本步驟
              : 一般 Tarball 套件安裝的建議事項(xiàng)( 如何移除?升級(jí)? )
              : 一個(gè)簡(jiǎn)單的范例、利用 ntp 來示范
              : 利用 patch 更新原始碼
            函式庫(kù)管理
              : 動(dòng)態(tài)與靜態(tài)函式庫(kù)
              : ldconfig 與 /etc/ld.so.conf, ldd,
            檢驗(yàn)套件軟件的正確性
              : md5sum
            重點(diǎn)回顧
            參考資源
            課后練習(xí)

            前言:
            如果鳥哥想要在我的 Linux 服務(wù)器上面跑網(wǎng)頁(yè)服務(wù)器( WWW server )這項(xiàng)服務(wù),那么我應(yīng)該要做些什么事呢?呵呵!當(dāng)然就一定需要『安裝網(wǎng)頁(yè)服務(wù)器的套件』啰! 如果鳥哥的服務(wù)器上面沒有這個(gè)套件的話,那當(dāng)然也就無法啟用 WWW 的服務(wù)啦!所以啦,想要在您的 Linux 上面進(jìn)行一些有的沒的功能,學(xué)會(huì)『如何安裝套件』是很重要的一個(gè)課題!
             
            咦!安裝套件有什么難的?在 Windows 操作系統(tǒng)上面安裝套件時(shí),不是只要一直給他按『下一步』就可以安裝妥當(dāng)了嗎?話是這樣說沒錯(cuò)啦,不過,也由于如此,所以在 Windows 系統(tǒng)上面的軟件都是一模一樣的,也就是說,您『無法修改該軟件的原始程序代碼』,因此,萬(wàn)一您想要增加或者減少該軟件的某些功能時(shí),呵呵!大概只能求助于當(dāng)初發(fā)行該軟件套件的廠商了!
             
            或許你會(huì)說:『唉呦!我不過是一般人,不會(huì)用到多余的功能,所以不太可能會(huì)更動(dòng)到程序代碼的部分吧!?』如果您這么想的話,很抱歉~是有問題的!怎么說呢? 像目前網(wǎng)絡(luò)上面的病毒、黑客軟件、臭蟲程序等等,都可能對(duì)您的主機(jī)上面的某些軟件造成影響(這是因?yàn)檐浖_發(fā)者在寫作之初可能并沒有想到某些問題所致!),導(dǎo)致主機(jī)的當(dāng)機(jī)或者是其它數(shù)據(jù)損毀等等的傷害。如果您可以藉由安全信息單位所提供的修訂方式進(jìn)行修改,那么您將可以很快速的自行修補(bǔ)好該軟件的漏洞,而不必一定要等到套件開發(fā)商提供修補(bǔ)的程序包哩!要知道,提早補(bǔ)洞是很重要的一件事。
             
            這樣說可以了解 Linux 的優(yōu)點(diǎn)了嗎?!沒錯(cuò)!因?yàn)?Linux 上面的套件幾乎都是經(jīng)過 GPL 的授權(quán),所以每個(gè)套件幾乎均提供原始程序代碼,并且您可以自行修改該程序代碼,以符合您個(gè)人的需求呢!很棒吧!這就是開放源碼( Open source )的優(yōu)點(diǎn)啰!不過,到底什么是開放源碼?這些程序代碼是什么咚咚?又 Linux 上面可以執(zhí)行的相關(guān)套件檔案與開放源碼之間是如何轉(zhuǎn)換的?不同版本的 Linux 之間能不能使用同一個(gè)執(zhí)行檔?或者是該執(zhí)行檔需要由原始程序代碼的部分重新進(jìn)行轉(zhuǎn)換?這些都是需要厘清觀念的。底下我們先就原始程序代碼與可執(zhí)行檔來進(jìn)行說明。
             

            什么是開放源碼、編譯器與可執(zhí)行檔?
            在討論程序代碼是什么之前,我們先來談?wù)撘幌率裁词强蓤?zhí)行檔?我們說過,在 Linux 系統(tǒng)上面,一個(gè)檔案能不能被執(zhí)行看的是有沒有可執(zhí)行的那個(gè)權(quán)限( 具有 x permission ),不過,Linux 系統(tǒng)上真正認(rèn)識(shí)的可執(zhí)行文件其實(shí)是二進(jìn)制檔案( binary file ),例如 /usr/bin/passwd, /bin/touch 這些個(gè)檔案即為 binary 的可執(zhí)行檔案!或許您會(huì)說,咦! shell scripts 不是也可以執(zhí)行嗎?!其實(shí) shell scripts 只是利用 shell ( 例如 bash )這支程序的功能進(jìn)行一些判斷式,而最終執(zhí)行的除了 bash 提供的功能外,仍是呼叫一些已經(jīng)編譯好的 binary 檔案來執(zhí)行的呢!( bash 本身就是 binary file 喔!)那么我怎么知道一個(gè)檔案是否為 binary 呢?!還記得我們?cè)? Linux 檔案與目錄管理 里面提到的 file 這個(gè)指令的功能嗎?!對(duì)啦!用他就是了!我們現(xiàn)在來測(cè)試一下:
             
            # 先以系統(tǒng)的檔案測(cè)試看看:
            [root@test root]# file /bin/bash
            /bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
             
            # 如果是我們?cè)? shell script 那個(gè)章節(jié)寫的 test01-hello.sh 檔案呢?
            [root@test root]# file test01-hello.sh
            test01-hello.sh: Bourne-Again shell script text executable
            ? 
            看到了吧!如果是 binary file 而且是可以執(zhí)行的時(shí)候,他就會(huì)顯示執(zhí)行文件類別 ( ELF 32-bit LSB executable ),同時(shí)會(huì)說明是否使用動(dòng)態(tài)函式庫(kù)( shared libs ),而如果是一般的 script ,那他就會(huì)顯示出 text executables 之類的字樣!(事實(shí)上,test01-hello.sh 的數(shù)據(jù)顯示出 Bourne-Again ... 那一行,是因?yàn)槟?scripts 上面第一行有宣告 #!/bin/bash 的緣故,如果您將 script 的第一行拿掉,呵呵!那么不管 test01-hello.sh 的權(quán)限為何,他其實(shí)顯示的是 ASCII 文字文件的信息喔!)
             
            既然 Linux 操作系統(tǒng)真正認(rèn)識(shí)的其實(shí)是 binary file ,那么我們是如何做出這樣的一支 binary? 的程序呢?!首先,我們必須要寫程序,用什么東西寫程序?就是一般的文書處理器啊!我都喜歡使用 vi 來進(jìn)行程序的撰寫,寫完的程序就是所謂的原始程序代碼啰!這個(gè)程序代碼檔案其實(shí)就是一般的純文字文件( text file )。在完成這個(gè)原始碼檔案的編寫之后,再來就是要將這個(gè)檔案『編譯』成為操作系統(tǒng)看的懂得 binary file 啰!而要編譯自然就需要『編譯器』來動(dòng)作,經(jīng)過編譯器的編譯之后,就會(huì)產(chǎn)生一支可以執(zhí)行的 binary file 啰。
             
            舉個(gè)例子來說,在 Linux 上面最標(biāo)準(zhǔn)的程序語(yǔ)言為 C ,所以我使用 C 的語(yǔ)法進(jìn)行原始程序代碼的書寫,寫完之后,以 Linux 上標(biāo)準(zhǔn)的 C 語(yǔ)言編譯器 gcc 這支程序來編譯,就可以制作一支可以執(zhí)行的 binary file 啰。整個(gè)的流程有點(diǎn)像這樣:
             

            圖一、簡(jiǎn)易的 gcc 編譯流程
             
            事實(shí)上,在編譯的過程當(dāng)中,還會(huì)產(chǎn)生所謂的目標(biāo)文件( Object file ),這些檔案是以 *.o 的附文件名樣式存在的!至于 C 語(yǔ)言的原始碼檔案通常以 *.c 作為附檔名。此外,有的時(shí)候,我們會(huì)在程序當(dāng)中『引用、呼叫』其它的外部子程序,或者是利用其它套件提供的『函數(shù)功能』,這個(gè)時(shí)候,我們就必須要在編譯的過程當(dāng)中,將該函式庫(kù)給他加進(jìn)去,如此一來,編譯器就可以將所有的程序代碼與函式庫(kù)作一個(gè)連結(jié)( Link )以產(chǎn)生正確的執(zhí)行檔啰。

            什么是函式庫(kù)?
            在前一小節(jié)的圖一示意圖中,在編譯的過程里面有提到函式庫(kù)。好啦,那么什么是函式庫(kù)呢?先舉個(gè)例子來說,我們的 Linux 系統(tǒng)上,系統(tǒng)通常已經(jīng)提供一個(gè)可以進(jìn)行身份驗(yàn)證的模塊,稱為 PAM ,這個(gè) PAM 提供的功能可以讓很多的程序在被執(zhí)行的時(shí)候,除了可以驗(yàn)證使用者登入的信息外,還可以將身份確認(rèn)的數(shù)據(jù)記錄在登錄文件( log file, 請(qǐng)查閱后續(xù)的 認(rèn)識(shí)登錄檔 一文 )里面,以方便系統(tǒng)管理員的追蹤!既然有這么好用的功能,那如果我要編寫具有身份認(rèn)證功能的程序時(shí),直接引用該 PAM 的功能就好啦,如此一來,我就不需要重新設(shè)計(jì)認(rèn)證機(jī)制啰!也就是說,只要在我寫的程序代碼里面,設(shè)定去呼叫 PAM 的函式功能,呵呵!我的程序就可以利用 Linux 原本就有的身份認(rèn)證的程序咯!除此之外,其實(shí)我們的 Linux 核心( kernel )也提供了相當(dāng)多的函式庫(kù)來給硬件開發(fā)者利用喔。
             
            函式庫(kù)又分為動(dòng)態(tài)與靜態(tài)函式庫(kù),這兩個(gè)咚咚的分別我們?cè)诤竺娴恼鹿?jié)再加以說明。這里我們以一個(gè)簡(jiǎn)單的流程圖,來示意一支有呼叫外部函式庫(kù)的程序的執(zhí)行情況。
             

            圖二、程序引用函式庫(kù)的示意圖
             
            很簡(jiǎn)單的示意圖啊!^_^!而如果要在程序里面加入引用的函式庫(kù),就需要如圖一所示,亦即在編譯的過程當(dāng)中,就需要加入函式庫(kù)的相關(guān)設(shè)定啰。
             
            事實(shí)上, Linux 的核心提供很多的核心相關(guān)函式庫(kù)與外部參數(shù),這些核心功能在設(shè)計(jì)硬件的驅(qū)動(dòng)程序的時(shí)候是相當(dāng)有用的信息,這些核心相關(guān)信息大多放置在 /usr/include, /lib, /usr/lib 里面哩!我們?cè)诒菊碌暮罄m(xù)小節(jié)再來探討。

            什么是? make 與 configure ?
            事實(shí)上,使用類似 gcc 的編譯器來進(jìn)行編譯的過程并不簡(jiǎn)單,因?yàn)槌嗣總€(gè)主程序與子程序均需要寫上一筆編譯過程的指令外,還需要寫上最終的連結(jié)程序。程序代碼小的時(shí)候還好,如果是類似 WWW 服務(wù)器軟件( 例如 Apache ),或者是類似核心的原始碼,動(dòng)則數(shù)百 MBytes 的資料量,呵呵!指令會(huì)寫到瘋掉~這個(gè)時(shí)候,我們就可以使用 make 這個(gè)指令的相關(guān)功能來進(jìn)行編譯過程的指令簡(jiǎn)化了!
             
            當(dāng)執(zhí)行 make 時(shí),make 會(huì)在當(dāng)時(shí)的目錄下搜尋 Makefile ( or makefile ) 這個(gè)文字文件,而 Makefile 里面則記錄了原始碼如何編譯的詳細(xì)信息!? make 會(huì)自動(dòng)的判別原始碼是否經(jīng)過變動(dòng)了,而自動(dòng)更新執(zhí)行檔,是軟件工程師相當(dāng)好用的一個(gè)輔助工具呢!
             
            咦!make 是一支程序,會(huì)去找 Makefile ,那 Makefile 怎么寫?呵呵!通常軟件開發(fā)商都會(huì)寫一支偵測(cè)程序來偵測(cè)使用者的作業(yè)環(huán)境,以及該作業(yè)環(huán)境是否有軟件開發(fā)商所需要的其它功能,該偵測(cè)程序偵測(cè)完畢后,就會(huì)主動(dòng)的建立這個(gè) Makefile 的規(guī)則檔案啦!通常這支偵測(cè)程序的文件名為 configure 或者是 config 。
             
            咦!?那為什么要偵測(cè)作業(yè)環(huán)境呢?!在 什么是 Linux 那個(gè)章節(jié)當(dāng)中,不是有提到 Linux 不過就是一個(gè)核心嗎?!是這樣沒錯(cuò)啦!但是您必須要了解的是,某些軟件套件需要一些相關(guān)的套件輔助,并且,某些驅(qū)動(dòng)程序則是適用在不同的核心系統(tǒng)( 因?yàn)楹诵奶峁┑暮綆?kù)可能并不相同,例如 kernel 2.2.xx 與 kernel 2.4.xx 就不太一樣! ),并且每個(gè) Linux distribution 所提供的函式庫(kù)名稱與路徑可能也不太一樣,所以說,在 Mandrake 上面可以執(zhí)行的一個(gè) binary file ,直接復(fù)制到 Red Hat 平臺(tái)上,可不見得可以順利執(zhí)行( 事實(shí)上,是不太可能可以執(zhí)行啦! ^_^ )。所以啦,原始碼寫出來之后,需要針對(duì)不同的作業(yè)環(huán)境來進(jìn)行編譯的行為吶!這個(gè)時(shí)候就很需要 configure 以及 make 的功能啊!
             
            詳細(xì)的 make 用法與 Makefile 規(guī)則,在后續(xù)的小節(jié)里面再探討啰!

            什么是 Tarball 的套件 ?
            從前面幾個(gè)小節(jié)的說明來看,我們知道所謂的原始程序代碼,其實(shí)就是一些寫滿了程序代碼的純文本文件。那我們從前面的 檔案的壓縮與打包 章節(jié)當(dāng)中,也了解了純文字文件其實(shí)是很浪費(fèi)硬盤空間的一種檔案格式!( 想一想,一個(gè)核心的原始碼檔案大約要 200~300 MB 以上,如果每個(gè)人都去下載這樣的一個(gè)核心檔案,呵呵!那么網(wǎng)絡(luò)頻寬不被吃的死翹翹才怪呢! )所以啦,如果能夠?qū)⑦@些原始碼透過檔案的打包與壓縮技術(shù)來將檔案的數(shù)量與容量減小,不但讓使用者容易下載,套件開發(fā)商的網(wǎng)站頻寬也能夠節(jié)省很多很多啊!這就是 Tarball 檔案的由來啰!
             
            所謂的 Tarball 檔案,其實(shí)就是將套件的所有原始碼檔案先以 tar 打包,然后再以壓縮技術(shù)來壓縮,通常最常見的就是以 gzip 來壓縮了。因?yàn)槔昧?tar 與 gzip 的功能,所以 tarball 檔案一般的附檔名就會(huì)寫成 *.tar.gz 或者是簡(jiǎn)寫為? *.tgz 啰!也就是說, Tarball 套件解壓縮之后,里面的檔案通常就會(huì)有:
            • 原始程序代碼檔案;
            • 偵測(cè)程序檔案( 可能是 configure 或 config 等檔名 );
            • 本套件的簡(jiǎn)易說明與安裝說明( INSTALL 或 README )。
            其中最重要的是那個(gè) INSTALL 或者是 README 這兩個(gè)檔案,通常您只要能夠參考這兩個(gè)檔案,呵呵! Tarball 套件的安裝是很簡(jiǎn)單的啦!我們?cè)诤竺娴恼鹿?jié)會(huì)再繼續(xù)介紹 Tarball 這個(gè)玩意兒。

            如何安裝與升級(jí)套件
            將原始碼作了一個(gè)簡(jiǎn)單的介紹,也知道了系統(tǒng)其實(shí)認(rèn)識(shí)的可執(zhí)行檔是 binary file 之后,好了,得要聊一聊,那么怎么安裝與升級(jí)一個(gè) Tarball 的套件?為什么要安裝一個(gè)新的套件呢?當(dāng)然是因?yàn)槲覀兊闹鳈C(jī)上面沒有該套件啰!那么,為何要升級(jí)呢?!原因可能有底下這些:
            • 需要新的功能,但舊有主機(jī)的舊版套件并沒有,所以需要升級(jí)到新版的套件;
            • 舊版本的套件上面可能有安全上的顧慮,所以需要更新到新版的套件;
            • 舊版的套件執(zhí)行效能不彰,或者執(zhí)行的能力不能讓管理者滿足。
            在上面的需求當(dāng)中,尤其需要注意的是第二點(diǎn),當(dāng)一個(gè)套件有安全上的顧慮時(shí),千萬(wàn)不要懷疑,趕緊更新套件吧!否則造成網(wǎng)絡(luò)危機(jī),那可不是鬧著玩的!那么更新的方法有哪些呢?基本上更新的方法可以分為兩大類,分別是:
            • 直接以原始碼透過編譯來安裝與升級(jí);
            • 直接以編譯好的 binary file 來安裝與升級(jí)。
            上面第一點(diǎn)很簡(jiǎn)單,就是直接以 Tarball 在自己的機(jī)器上面進(jìn)行偵測(cè)、編譯、安裝與設(shè)定等等動(dòng)作來升級(jí)就是了。不過,這樣的動(dòng)作雖然讓使用者在安裝過程當(dāng)中具有很高的彈性,但畢竟是比較麻煩一點(diǎn),如果 Linux distribution 廠商能夠針對(duì)自己的作業(yè)平臺(tái)先進(jìn)行編譯等過程,再將編譯好的 binary file 釋出的話,那由于我的系統(tǒng)與該 Linux distribution 的環(huán)境是相同的,所以他所釋出的 binary file 就可以在我的機(jī)器上面直接安裝啦!省略了偵測(cè)與編譯等等繁雜的過程呢!目前很多 binary file 升級(jí)的機(jī)制呢,包括有 Red Hat 發(fā)展的 RPM 與 up2date, yum 等在線更新模式;Mandrake 的 urpmi 套件更新方式; Debian 使用的 dpkg ; Sun Unix 使用的 pkg ,以及目前很流行的 apt 在線更新模式等等,以使用率來說,目前最傳統(tǒng)的是以 Tarball 直接進(jìn)行編譯的安裝與升級(jí),而另一個(gè)則是以 RPM 相關(guān)的機(jī)制來進(jìn)行安裝與升級(jí)啰!本章節(jié)主要針對(duì) Tarball ,至于 RPM 則留待下個(gè)章節(jié)再來介紹呢!
             
            好了,那么一個(gè)套件的 Tarball 是如何安裝的呢?基本流程是這樣的啦:
            1. 將 Tarball 由廠商的網(wǎng)頁(yè)下載下來;
            2. 將 Tarball 解開,產(chǎn)生很多的原始碼檔案;
            3. 開始以 gcc 進(jìn)行原始碼的編譯( 會(huì)產(chǎn)生目標(biāo)文件 object files );
            4. 然后以 gcc 進(jìn)行函式庫(kù)、主、子程序的連結(jié),以形成主要的 binary file;
            5. 將上述的 binary file 以及相關(guān)的設(shè)定文件安裝至自己的主機(jī)上面。
            上面第 3, 4 步驟當(dāng)中,我們可以透過 make 這個(gè)指令的功能來簡(jiǎn)化他,所以整個(gè)步驟其實(shí)是很簡(jiǎn)單的啦!只不過您就得需要至少有 gcc 以及 make 這兩個(gè)套件在您的 Linux 系統(tǒng)里面才行喔!詳細(xì)的過程以及需要的套件我們?cè)诤竺娴恼鹿?jié)繼續(xù)來介紹的啦!

            一個(gè)簡(jiǎn)單的范例:
              經(jīng)過上面的介紹之后,您應(yīng)該比較清楚的知道原始碼、編譯器、函式庫(kù)與執(zhí)行檔之間的相關(guān)性了。不過,詳細(xì)的流程可能還是不很清楚,所以,在這里我們以一個(gè)簡(jiǎn)單的程序范例來說明整個(gè)編譯的過程喔!趕緊進(jìn)入 Linux 系統(tǒng),實(shí)地的操作一下底下的范例呢!
               

              印出 Hello World
              我們以 Linux 上面最常見的 C 語(yǔ)言來撰寫第一支程序!第一支程序最常作的就是.....在屏幕上面印出『Hello World!』的字樣~當(dāng)然,這里我們是以簡(jiǎn)單的 C 語(yǔ)言來撰寫,如果您對(duì)于 C 有興趣的話,那么請(qǐng)自行購(gòu)買相關(guān)的書籍喔! ^_^好了,不啰唆,立刻編輯第一支程序吧!( 注:請(qǐng)先確認(rèn)您的 Linux 系統(tǒng)里面已經(jīng)安裝了 gcc 了喔!如果尚未安裝 gcc 的話,請(qǐng)先參考下一節(jié)的 RPM 安裝法,先安裝好 gcc 之后,再回來閱讀本章 )
               
              # 1. 先編輯原始碼:
              [guest@test guest]# vi hello.c<==注意一下, C 語(yǔ)言用 .c 的附檔名
              #include <stdio.h>
              int main(void)
              {
              ??????? printf("Hello World\n");
              }
               
              # 上面是 C 語(yǔ)言的語(yǔ)法,那個(gè)第一行的 # 并不是批注喔!如果您擔(dān)心
              # 輸入錯(cuò)誤,請(qǐng)到底下的連結(jié)下載這個(gè)檔案:
              # http://linux.vbird.org/download/books/basic/source_code/hello.c
               
              # 2. 開始將原始碼編譯成為可執(zhí)行的 binary file :
              [guest@test guest]# gcc hello.c
              # 這個(gè)時(shí)候,在本目錄下會(huì)產(chǎn)生一個(gè)名為 a.out 的執(zhí)行檔!
              # 在預(yù)設(shè)的狀態(tài)下,如果我們直接以 gcc 編譯原始碼,并且沒有加上
              # 任何參數(shù),則執(zhí)行檔的檔名會(huì)被自動(dòng)設(shè)定為 a.out 這個(gè)文件名稱
               
              # 3. 執(zhí)行一下這個(gè)檔案:
              [guest@test guest]# ./a.out
              Hello World? <==呵呵!成果出現(xiàn)了!
              ? 
              好了,上面的例子很簡(jiǎn)單吧!那個(gè) hello.c 就是原始碼,而 gcc 就是編譯器,至于 a.out 就是編譯成功的可執(zhí)行 binary file 啰!咦!如果我想要產(chǎn)生目標(biāo)文件( object file )來進(jìn)行其它的動(dòng)作( 在較大的套件當(dāng)中,就需要使用多個(gè)目標(biāo)文件來進(jìn)行相關(guān)的連結(jié) ),而且執(zhí)行檔的檔名也不要用預(yù)設(shè)的 a.out ,那該如何是好?可以將上面的第 2 個(gè)步驟改成這樣:
               
              [guest@test guest]# gcc -c hello.c
              # 會(huì)產(chǎn)生一個(gè)名為 hello.o 的目標(biāo)文件,object file 的附檔名為 *.o 喔!
               
              [guest@test guest]# gcc -o hello hello.o
              # 這個(gè)步驟是利用 hello.o 這個(gè)目標(biāo)文件制作出一個(gè)名為 hello 的執(zhí)行檔
              # 詳細(xì)的 gcc 語(yǔ)法我們會(huì)在后續(xù)章節(jié)中繼續(xù)介紹!
              # 透過這個(gè)動(dòng)作后,我們可以得到 hello 及 hello.o 兩個(gè)檔案,
              # 真正可以執(zhí)行的是 hello 這個(gè) binary file 喔!
               
              # 3. 執(zhí)行一下這個(gè)檔案:
              [guest@test guest]# ./hello
              Hello World
              ? 
              或許您會(huì)覺得,咦!只要一個(gè)動(dòng)作作出 a.out 就好了,干嘛還要先制作目標(biāo)文件再做成執(zhí)行檔呢?!呵呵!透過下個(gè)范例,您就可以知道為什么啦!

              子程序的編譯
              如果我們?cè)谝粋€(gè)主程序里面又呼叫了另一個(gè)子程序呢!?這是很常見的一個(gè)程序?qū)懛ǎ驗(yàn)榭梢院?jiǎn)化整個(gè)程序的易讀性!在底下的例子當(dāng)中,我們以 thanks.c 這個(gè)主程序去呼叫 thanks_2.c 這個(gè)子程序,寫法很簡(jiǎn)單:
               
              # 1. 先編輯原始碼 thanks.c 與 thanks_2.c:
              [guest@test guest]# vi thanks.c
              #include <stdio.h>
              int main(void)
              {
              ??????? printf("Hello World\n");
              ??????? thanks_2();
              }
               
              # 上面的 thanks_2(); 那一行就是呼叫子程序啦!

              [guest@test guest]# vi thanks_2.c
              void thanks_2(void)
              {
              ??????? printf("Thank you!\n");
              }
               
              # 上面這兩個(gè)檔案您可以到底下下載
              # http://linux.vbird.org/download/books/basic/source_code/thanks.c
              # http://linux.vbird.org/download/books/basic/source_code/thanks_2.c
               
              # 2. 開始將原始碼編譯成為可執(zhí)行的 binary file :
              [guest@test guest]# gcc -c thanks.c thanks_2.c
              # 產(chǎn)生了兩個(gè)目標(biāo)文件!
              [guest@test guest]# gcc -o thanks thanks.o thanks_2.o
               
              # 3. 執(zhí)行一下這個(gè)檔案:
              [guest@test guest]# ./thanks
              Hello World
              Thank you!

              ? 
              知道為什么要制作出目標(biāo)文件了嗎?!由于我們的原始碼檔案有時(shí)并非僅只有一個(gè)檔案,所以我們無法直接進(jìn)行編譯。這個(gè)時(shí)候就需要先產(chǎn)生目標(biāo)文件,然后再以連結(jié)制作成為 binary 可執(zhí)行檔。另外,如果有一天,您更新了 thanks_2.c 這個(gè)檔案的內(nèi)容,則您只要重新編譯 thanks_2.c 來產(chǎn)生新的 thanks_2.o ,然后再以連結(jié)制作出新的 binary 可執(zhí)行檔即可!而不必重新編譯其它沒有更動(dòng)過的原始碼檔案。這對(duì)于軟件開發(fā)者來說,是一個(gè)很重要的功能,因?yàn)橛袝r(shí)候要將諾大的原始碼全部編譯完成,會(huì)花很長(zhǎng)的一段時(shí)間呢!
               
              此外,如果您想要讓程序在執(zhí)行的時(shí)候具有比較好的效能,或者是其它的除錯(cuò)功能時(shí),可以在編譯的過程里面加入適當(dāng)?shù)膮?shù),例如底下的例子:
               
              [guest@test guest]# gcc -O -c thanks.c thanks_2.c
              # -O 為產(chǎn)生最佳化的參數(shù)
              [guest@test guest]# gcc -Wall -c thanks.c thanks_2.c
              thanks.c: In function `main':
              thanks.c:5: warning: implicit declaration of function `thanks_2'
              thanks.c:6: warning: control reaches end of non-void function
              thanks_2.c: In function `thanks_2':
              thanks_2.c:3: warning: implicit declaration of function `printf'
              # -Wall 為產(chǎn)生更詳細(xì)的編譯過程信息。上面的訊息為警告訊息( warning )
              # 所以不用理會(huì)也沒有關(guān)系!
              ? 

              加入連結(jié)的函式庫(kù)
            剛剛我們都僅只是在屏幕上面印出一些字眼而已,如果說要計(jì)算數(shù)學(xué)公式呢?!例如我們想要計(jì)算出三角函數(shù)里面的 sin(90度角),要注意的是,大多數(shù)的程序語(yǔ)言都是使用徑度而不是一般我們?cè)谟?jì)算的『角度』, 180 度角約等于 3.14 徑度!嗯!那我們就來寫一下這個(gè)程序吧!
             
            [guest@test guest]# vi sin.c
            #include <stdio.h>
            int main(void)
            {
            ??????? float value;
            ??????? value = sin ( 3.14 / 2 );
            ??????? printf("%f\n",value);
            }
            # 上面這個(gè)檔案的內(nèi)容可以在底下取得!
            # http://linux.vbird.org/download/books/basic/source_code/sin.c
            ? 
            那要如何編譯這支程序呢?我們先直接編譯看看:
             
            [guest@test guest]# gcc sin.c
            /tmp/ccppUCx8.o(.text+0x1e): In function `main':
            : undefined reference to `sin'
            collect2: ld returned 1 exit status
            ? 
            特別注意上面的說明,唉啊!怎么沒有編譯成功?它說的是『undefined reference to sin』,說的是『沒有 sin 的相關(guān)定義參考值!』,為什么會(huì)這樣呢?這是因?yàn)? C 語(yǔ)言里面的 sin 函示是寫在 libm.so 這個(gè)函式庫(kù)中,而我們并沒有在原始碼里面加入相關(guān)的說明,所以當(dāng)然就需要在編譯與連結(jié)的時(shí)候?qū)⑦@個(gè)函式庫(kù)給他連結(jié)進(jìn)執(zhí)行檔里面啊!所以我們可以這樣做:
             
            [guest@test guest]# gcc sin.c -lm -L/lib -L/usr/lib
            # 特別注意,那個(gè) -lm 可以拆開成兩部份來看,
            # -l 是『加入某個(gè)函式庫(kù)(library)』的意思,而
            # m 則是 libm.so 這個(gè)函式庫(kù),其中, lib 與附檔名(.a 或 .so)不需要寫
            # 所以 -lm 表示使用 libm.so (或 libm.a) 這個(gè)函式庫(kù)的意思~
            # 至于那個(gè) -L 后面接的路徑呢?這表示:
            #『我要的函式庫(kù) libm.so 請(qǐng)到 /lib 或 /usr/lib 里面搜尋!
            [guest@test guest]# ./a.out
            1.000000
            ? 
            上面的說明很清楚了吧!!不過,要注意的是,由于 Linux 預(yù)設(shè)是將函式庫(kù)放置在 /lib 與 /usr/lib 當(dāng)中,所以您沒有寫 -L/lib 與? -L/usr/lib 也沒有關(guān)系的!不過,萬(wàn)一哪天您使用的函式庫(kù)并非放置在這兩個(gè)目錄下,那么 -L/path 就很重要了!否則會(huì)找不到函式庫(kù)喔!
             
            除了連結(jié)的函式庫(kù)之外,您或許已經(jīng)發(fā)現(xiàn)一個(gè)奇怪的地方,那就是在我們的 sin.c 當(dāng)中第一行『 #include <stdio.h>』,這行說的是要將一些定義數(shù)據(jù)由 stdio.h 這個(gè)檔案讀入,這包括 printf 的相關(guān)設(shè)定。這個(gè)檔案其實(shí)是放置在 /usr/include/stdio.h 的!那么萬(wàn)一這個(gè)檔案并非放置在這里呢?那么我們就可以使用底下的方式來定義出要讀取的 include 檔案放置的目錄:
             
            [guest@test guest]# gcc sin.c -lm -I/usr/include
            ? 
            -I/path 后面接的路徑( Path )就是設(shè)定要去搜尋相關(guān)的 include 檔案的目錄啦!不過,同樣的,默認(rèn)值是放置在 /usr/include 底下,除非您的 include 檔案放置在其它路徑,否則也可以略過這個(gè)項(xiàng)目!
             
            透過上面的幾個(gè)小范例,您應(yīng)該對(duì)于 gcc 以及原始碼有一定程度的認(rèn)識(shí)了,再接下來,我們來稍微整理一下 gcc 的簡(jiǎn)易使用方法吧!

              gcc 的用法
                前面說過, gcc 為 Linux 上面最標(biāo)準(zhǔn)的編譯器,這個(gè) gcc 是由 GNU 所維護(hù)的,有興趣的朋友請(qǐng)自行前往參考。既然 gcc 對(duì)于 Linux 上的 Open source 是這么樣的重要,所以底下我們就列舉幾個(gè) gcc 常見的參數(shù),如此一來大家應(yīng)該更容易了解原始碼的各項(xiàng)功能吧?!
                 
                # 僅將原始碼編譯成為目標(biāo)文件,并不制作連結(jié)等功能:
                [guest@test guest]# gcc -c hello.c
                # 會(huì)自動(dòng)的產(chǎn)生 hello.o 這個(gè)檔案,但是并不會(huì)產(chǎn)生 binary 執(zhí)行檔。
                 
                # 在編譯的時(shí)候,依據(jù)作業(yè)環(huán)境給予最佳化執(zhí)行速度
                [guest@test guest]# gcc -O hello.c -c
                # 會(huì)自動(dòng)的產(chǎn)生 hello.o 這個(gè)檔案,并且進(jìn)行最佳化喔!
                 
                # 在進(jìn)行 binary file 制作時(shí),將連結(jié)的函式庫(kù)與相關(guān)的路徑填入
                [guest@test guest]# gcc sin.c -lm -L/usr/lib -I/usr/include
                # 這個(gè)指令較常下達(dá)在最終連結(jié)成 binary file 的時(shí)候,
                # -lm 指的是 libm.so 或 libm.a 這個(gè)函式庫(kù)檔案;
                # -L 后面接的路徑是剛剛上面那個(gè)函式庫(kù)的搜尋目錄;
                # -I 后面接的是原始碼內(nèi)的 include 檔案之所在目錄。
                 
                # 將編譯的結(jié)果輸出成某個(gè)特定檔名
                [guest@test guest]# gcc -o hello hello.c
                # -o 后片接的是要輸出的 binary file 檔名
                 
                # 在編譯的時(shí)候,輸出較多的訊息說明
                [guest@test guest]# gcc -o hello hello.c -Wall
                # 加入 -Wall 之后,程序的編譯會(huì)變的較為嚴(yán)謹(jǐn)一點(diǎn),
                # 所以警告訊息也會(huì)顯示出來!
                ? 
                比較重要的大概就是這一些。另外,我們通常稱 -Wall 或者 -O 這些非必要的參數(shù)為旗標(biāo)( FLAGS ),因?yàn)槲覀兪褂玫氖?GCC ,所以有時(shí)候也會(huì)簡(jiǎn)稱這些旗標(biāo)為 CCFLAGS ,這些變量偶爾會(huì)被使用的喔!尤其是在后頭會(huì)介紹的 make 相關(guān)的用法時(shí),更是重要的很吶! ^_^

            make 的簡(jiǎn)易用法
            在前言的部分我們提到過 make 的功能是可以簡(jiǎn)化編譯過程里面所下達(dá)的指令,同時(shí)還具有很多很方便的功能!那么底下咱們就來試看看使用 make 簡(jiǎn)化下達(dá)編譯指令的流程吧!
             

            為什么要用 make
            先來想象一個(gè)案例,假設(shè)我的執(zhí)行檔里面包含了四個(gè)原始碼檔案,分別是 main.c haha.c sin_value.c cos_value.c 這四個(gè)檔案,這四個(gè)檔案您可以到 http://linux.vbird.org/download/books/basic/source_code/main.tgz 來下載,由于這四個(gè)檔案里面包含了相關(guān)性,并且還用到數(shù)學(xué)函式在里面,所以如果您想要讓這個(gè)程序可以跑,那么就需要這樣編譯:
             
            [guest@test guest]# gcc -c main.c
            [guest@test guest]# gcc -c haha.c
            [guest@test guest]# gcc -c sin_value.c
            [guest@test guest]# gcc -c cos_value.c
            # 先以上面的動(dòng)作制作出四個(gè)目標(biāo)文件,然后再進(jìn)行下面的動(dòng)作:
             
            [guest@test guest]# gcc -o main main.o haha.o sin_value.o \
            > cos_value.o -lm -L/usr/lib -L/lib
            # 這樣就可以制作出? main 這個(gè)執(zhí)行檔啰!執(zhí)行看看吧!
             
            [guest@test guest]# ./main
            HaHa! I'm the King of the world
            0.706825
            0.707388
             
            呵呵!要做好多動(dòng)作啊!真是麻煩,如果可以的話,能不能一個(gè)步驟就給他完成上面所有的動(dòng)作呢?試看看在這個(gè)目錄下建立一個(gè) makefile 檔案,內(nèi)容如下:
             
            # 1. 先建立編譯的規(guī)則
            [guest@test guest]# vi makefile
            main: main.o haha.o sin_value.o cos_value.o
            ??????? gcc -o main main.o haha.o sin_value.o cos_value.o -lm
            # 注意: gcc 之前是 <tab> 按鍵產(chǎn)生的空格喔!
             
            # 2. 嘗試給他建立規(guī)則看看
            [guest@test guest]# rm -f main *.o <==先將之前的目標(biāo)文件去除
            [guest@test guest]# make
            cc??? -c -o main.o main.c
            cc??? -c -o haha.o haha.c
            cc??? -c -o sin_value.o sin_value.c
            cc??? -c -o cos_value.o cos_value.c
            gcc -o main main.o haha.o sin_value.o cos_value.o -lm
            # 這個(gè)時(shí)候 make 會(huì)主動(dòng)去讀取 makefile 這個(gè)檔案的內(nèi)容,
            # 并根據(jù)內(nèi)容直接去給他編譯起相關(guān)的執(zhí)行檔啰!
             
            # 3. 如果再執(zhí)行一次 make 會(huì)怎樣?!
            [guest@test guest]# make
            make: `main' is up to date.
            # 看到了吧?!是否很方便呢?!
             
            或許您會(huì)說:『如果我建立一個(gè) shell script 來將上面的所有動(dòng)作都集結(jié)在一起,不是具有同樣的效果嗎?』呵呵!效果當(dāng)然不一樣,以上面的測(cè)試為例,我們僅寫出 main 需要的目標(biāo)文件,結(jié)果 make 會(huì)主動(dòng)的去判斷每個(gè)目標(biāo)文件相關(guān)的原始碼檔案,并直接予以編譯,最后再直接進(jìn)行連結(jié)的動(dòng)作!哈哈!真的是很方便啊!此外,如果我們更動(dòng)過某些原始碼檔案,則 make 也可以主動(dòng)的判斷哪一個(gè)原始碼與相關(guān)的目標(biāo)文件檔案有更新過,并僅更新該檔案,如此一來,將可大大的節(jié)省很多編譯的時(shí)間呢!要知道,某些程序在進(jìn)行編譯的行為時(shí),會(huì)消耗很多的 CPU 資源呢!所以說, make 有這些好處:
            • 簡(jiǎn)化編譯時(shí)所需要下達(dá)的指令;
            • 若在編譯完成之后,修改了某個(gè)原始碼檔案,則 make 僅會(huì)針對(duì)被修改了的檔案進(jìn)行編譯,其它的 object file 不會(huì)被更動(dòng);
            • 最后可以依照相依性來更新( update )執(zhí)行檔。
            既然 make 有這么多的優(yōu)點(diǎn),那么我們當(dāng)然就得好好的了解一下 make 這個(gè)令人關(guān)心的家伙啦!而 make 里面最需要注意的大概就是那個(gè)規(guī)則檔案,也就是 makefile 這個(gè)檔案的語(yǔ)法啦!底下我們針對(duì) makefile 的語(yǔ)法來加以介紹啰。

            make 的基本語(yǔ)法與變量
            make 的語(yǔ)法可是相當(dāng)?shù)亩喽鴱?fù)雜的,有興趣的話可以到 http://www.gnu.org/software/make/manual/html_mono/make.html 去查閱相關(guān)的說明,鳥哥這里僅列出一些基本的規(guī)則,重點(diǎn)在于讓讀者們未來在接觸原始碼時(shí),不會(huì)太緊張啊! ^_^好了,基本的 makefile 規(guī)則是這樣的:
             
            標(biāo)的(target): 目標(biāo)文件1 目標(biāo)文件2
            <tab>? gcc -o 欲建立的執(zhí)行文件 目標(biāo)文件1 目標(biāo)文件2
             
            那個(gè)標(biāo)的(target)就是我們想要建立的信息,而目標(biāo)文件就是具有相關(guān)性的 object files ,那建立執(zhí)行文件的語(yǔ)法就是以 <tab> 按鍵開頭的那一行!特別給他留意喔,『命令列必須要以 tab 按鍵作為開頭』才行!他的規(guī)則基本上是這樣的:
            • 在 makefile 當(dāng)中的 # 代表批注;
            • <tab> 需要在命令行的第一個(gè)字符;
            • 標(biāo)的(target)與相依檔案(就是目標(biāo)文件)之間需以『:』隔開。
            同樣的,我們以剛剛上一個(gè)小節(jié)的范例進(jìn)一步說明,如果我想要有兩個(gè)以上的執(zhí)行動(dòng)作時(shí),例如下達(dá)一個(gè)指令就直接清除掉所有的目標(biāo)文件與執(zhí)行文件,該如何制作呢?
             
            # 1. 先建立編譯的規(guī)則
            [guest@test guest]# vi makefile
            main: main.o haha.o sin_value.o cos_value.o
            ??????? gcc -o main main.o haha.o sin_value.o cos_value.o -lm
            clean:
            ??????? rm -f main main.o haha.o sin_value.o cos_value.o
             
            # 2. 測(cè)試看看:
            [guest@test guest]# make clean
            rm -f main main.o haha.o sin_value.o cos_value.o
             
            如此一來,我們的 makefile 里面就具有至少兩個(gè)標(biāo)的,分別是 main 與 clean ,如果我們想要建立 main 的話,輸入『make main』,如果想要清除有的沒的,輸入『make clean』即可啊!而如果想要先清除目標(biāo)文件再編譯 main 這個(gè)程序的話,就可以這樣輸入:『make clean main』,如下所示:
             
            [guest@test guest]# make clean main
            rm -f main main.o haha.o sin_value.o cos_value.o
            cc??? -c -o main.o main.c
            cc??? -c -o haha.o haha.c
            cc??? -c -o sin_value.o sin_value.c
            cc??? -c -o cos_value.o cos_value.c
            gcc -o main main.o haha.o sin_value.o cos_value.o -lm
             
            這樣就很清楚了吧!?但是,您是否會(huì)覺得,咦! makefile 里面怎么重復(fù)的數(shù)據(jù)這么多啊!呵呵!沒錯(cuò)!所以我們可以再藉由 shell script 那時(shí)學(xué)到的『變數(shù)』來更簡(jiǎn)化 makefile 喔:
             
            [guest@test guest]# vi makefile
            LIBS = -lm
            OBJS = main.o haha.o sin_value.o cos_value.o
            main: ${OBJS}
            ??????? gcc -o main ${OBJS} ${LIBS}
            clean:
            ??????? rm -f main ${OBJS}
             
            與 bash shell script 的語(yǔ)法有點(diǎn)不太相同,變量的基本語(yǔ)法為:
            1. 變量與變量?jī)?nèi)容以『=』隔開,同時(shí)兩邊可以具有空格;
            2. 變量左邊不可以有 <tab> ,例如上面范例的第一行 LIBS 左邊不可以是 <tab>;
            3. 變量與變量?jī)?nèi)容在『=』兩邊不能具有『:』;
            4. 在習(xí)慣上,變數(shù)最好是以『大寫字母』為主;
            5. 運(yùn)用變量時(shí),以 ${變量} 或 $(變量) 使用;
            6. 在該 shell 的環(huán)境變量是可以被套用的,例如提到的 CFLAGS 這個(gè)變數(shù)!
            7. 在指令列模式也可以給予變量。
            由于 gcc 在進(jìn)行編譯的行為時(shí),會(huì)主動(dòng)的去讀取 CFLAGS 這個(gè)環(huán)境變量,所以,您可以直接在 shell 定義出這個(gè)環(huán)境變量,也可以在 makefile 檔案里面去定義,更可以在指令列當(dāng)中給予這個(gè)咚咚呢!例如:
             
            [guest@test guest]# make clean main "CFLAGS=-Wall"
            # 這個(gè)動(dòng)作在上 make 進(jìn)行編譯時(shí),會(huì)去取用 CFLAGS 的變量?jī)?nèi)容!
             
            也可以這樣:
             
            [guest@test guest]# vi makefile
            LIBS = -lm
            OBJS = main.o haha.o sin_value.o cos_value.o
            CFLAGS = -Wall
            main: ${OBJS}
            ??????? gcc -o main ${OBJS} ${LIBS}
            clean:
            ??????? rm -f main ${OBJS}
             
            咦!我可以利用指令列進(jìn)行環(huán)境變量的輸入,也可以在檔案內(nèi)直接指定環(huán)境變量,那萬(wàn)一這個(gè) CFLAGS 的內(nèi)容在指令列與 makefile 里面并不相同時(shí),以那個(gè)方式輸入的為主?呵呵!環(huán)境變量取用的規(guī)則是這樣的:
            1. make 指令列后面加上的環(huán)境變量為優(yōu)先;
            2. makefile 里面指定的環(huán)境變量第二;
            3. shell 原本具有的環(huán)境變量第三。
            此外,還有一些特殊的變量需要了解的喔:
            • $@:代表目前的標(biāo)的(target)
            所以我也可以將 makefile 改成:
             
            [guest@test guest]# vi makefile
            LIBS = -lm
            OBJS = main.o haha.o sin_value.o cos_value.o
            CFLAGS = -Wall
            main: ${OBJS}
            ??????? gcc -o $@ ${OBJS} ${LIBS}? <==那個(gè) $@ 就是 main !
            clean:
            ??????? rm -f main ${OBJS}
             
            這樣是否稍微了解了 makefile ( 也可能是 Makefile ) 的基本語(yǔ)法?這對(duì)于您未來自行修改原始碼的編譯規(guī)則時(shí),是很有幫助的喔! ^_^!

            Tarball 的管理與建議:
              好了!在我們知道了原始碼的相關(guān)信息之后,再來要了解的自然就是如何使用具有原始碼的 Tarball 來建立一個(gè)屬于自己的套件啰!從前面幾個(gè)小節(jié)的說明當(dāng)中,我們曉得其實(shí) Tarball 的安裝是可以跨平臺(tái)的因?yàn)?C 語(yǔ)言的程序代碼在各個(gè)平臺(tái)上面是可以共通的,只是需要的編譯器可能并不相同而已。例如 Linux 上面用 gcc 而 Windows 上面也有相關(guān)的 C 編譯器啊~所以呢,同樣的一組原始碼,既可以在 Mandrake Linux 上面編譯,也可以在 Red Hat Linux 上面編譯,當(dāng)然,也可以在大部分的 Unix 平臺(tái)上面編譯成功的!所以啰, Tarball 原始碼程序應(yīng)該可以在大部分的環(huán)境底下安裝成功的!舉例來說,鳥哥在上面幾個(gè)小節(jié)所提供的 C 程序是在 Red Hat 9 上面測(cè)試編譯的,那么您可以下載之后在自己的 Linux 環(huán)境下測(cè)試看看,我想,每個(gè)人應(yīng)該都可以順利的編譯成功的才是!因?yàn)? C 的語(yǔ)法是沒有不一樣的啊! ^_^
               
              如果萬(wàn)一沒有編譯成功怎么辦?很簡(jiǎn)單啊,透過修改小部分的程序代碼( 通常是因?yàn)楹苄〔糠值漠悇?dòng)而已 )就可以進(jìn)行跨平臺(tái)的移植了!也就是說,剛剛我們?cè)?Linux 底下寫的程序『理論上,是可以在 Windows 上面編譯的!』這就是原始碼的好處啦!所以說,如果朋友們想要學(xué)習(xí)程序語(yǔ)言的話,鳥哥個(gè)人是比較建議學(xué)習(xí)『具有跨平臺(tái)能力的程序語(yǔ)言』,例如 C 就是很不錯(cuò)的一個(gè)!
               
              唉啊!又扯遠(yuǎn)了~趕緊拉回來繼續(xù)說明我們的 Tarball 啦!
               

              使用原始碼管理套件所需要的基礎(chǔ)套件
            從原始碼的說明我們曉得要制作一個(gè) binary 執(zhí)行檔需要很多咚咚的呢!這包括底下這些基礎(chǔ)的套件:
            • gcc 或 cc 等 C 語(yǔ)言編譯器( compiler )

            • 這是一定要的啦!要將原始碼編譯成為可執(zhí)行的 binary 才行,所以當(dāng)然就需要編譯器啰!在 Linux 上面用的當(dāng)然就是 GNU 發(fā)展的 gcc 這個(gè)超好用的免費(fèi)的 C 編譯器啦!并且,很多在 Linux 平臺(tái)上面發(fā)展的套件的原始碼,原本就是以 gcc 為底來設(shè)計(jì)的呢。
               
            • make 及 autoconfig 等套件

            • 一般來說,以 Tarball 方式釋出的套件當(dāng)中,為了簡(jiǎn)化編譯的行程,通常都是配合前幾個(gè)小節(jié)提到的 make 這個(gè)指令來依據(jù)目標(biāo)檔案的相依性而進(jìn)行編譯。但是我們也知道說 make 需要 makefile 這個(gè)檔案的規(guī)則,那由于不同的系統(tǒng)里面可能具有的基礎(chǔ)套件環(huán)境并不相同,所以就需要偵測(cè)使用者的作業(yè)環(huán)境,好自行建立一個(gè) makefile 檔案。這個(gè)自行偵測(cè)的小程序也必須要藉由 autoconfig 這個(gè)相關(guān)的套件來輔助才行。
               
            • 需要 Kernel 提供的 Library 以及相關(guān)的 Include 檔案

            • 從前面的原始碼編譯過程,我們曉得函式庫(kù)( library )的重要性,同時(shí)也曉得有 include 檔案的存在。很多的套件在發(fā)展的時(shí)候都是直接取用系統(tǒng)核心提供的函式庫(kù)與 include 檔案的,這樣才可以與這個(gè)操作系統(tǒng)兼容啊!尤其是在『驅(qū)動(dòng)程序方面的套件』,例如網(wǎng)絡(luò)卡、聲卡、USB 等驅(qū)動(dòng)程序在安裝的時(shí)候,常常是需要核心提供的相關(guān)信息的。在 Red Hat 的系統(tǒng)當(dāng)中,這個(gè)核心相關(guān)的功能通常都是被包含在 kernel-source kernel-header 這些套件名稱當(dāng)中,所以記得要安裝這些套件喔!
            雖然 Tarball 的安裝上面相當(dāng)?shù)暮?jiǎn)單,如同我們前面幾個(gè)小節(jié)的例子,只要順著開發(fā)商提供的 README 與 INSTALL 檔案所載明的步驟來進(jìn)行,安裝是很容易的。但是我們卻還是常常會(huì)在 BBS 或者是新聞群組當(dāng)中發(fā)現(xiàn)這些留言:『我在執(zhí)行某個(gè)程序的偵測(cè)檔案時(shí),他都會(huì)告訴我沒有 gcc 這個(gè)套件,這是怎么回事?』還有:『我沒有辦法使用 make 耶!這是什么問題?』呵呵!這就是沒有安裝上面提到的那些基礎(chǔ)套件啦!
             
            咦!為什么使用者不安裝這些套件啊?呵呵!這是因?yàn)槟壳暗?Linux distribution 大多已經(jīng)偏向于桌上型計(jì)算機(jī)的使用,他們希望使用者能夠按照廠商自己的希望來安裝相關(guān)的套件即可,所以通常『預(yù)設(shè)』是沒有安裝 gcc 或者是 make 等套件的。所以啦,如果您希望未來可以自行安裝一些以 Tarball 方式釋出的套件時(shí),記得請(qǐng)自行挑選想要安裝的套件名稱喔!例如在 Mandrake 或者是 Red Hat 當(dāng)中記得選擇 Software Development 以及 Kernel SourceDevelopment 等相關(guān)字眼的群集呢。
             
            那萬(wàn)一我已經(jīng)安裝好一部 Linux 主機(jī),但是使用的是默認(rèn)值所安裝的套件,所以沒有 make, gcc 等咚咚,該如何是好?呵呵!問題其實(shí)不大啦,目前使用最廣泛的 Mandrake 或者是 Red Hat 大多是以 RPM( 下一章會(huì)介紹 )來安裝套件的,所以,您只要拿出當(dāng)初安裝 Linux 時(shí)的原版光盤,然后以下一章介紹的 RPM 來一個(gè)一個(gè)的加入到您的 Linux 主機(jī)里面就好啦!很簡(jiǎn)單的啦!

            Tarball 安裝的基本步驟
            我們提過以 Tarball 方式釋出的套件是需要重新編譯可執(zhí)行的 binary file 的。而 Tarball 是以 tar 這個(gè)指令來打包與壓縮的檔案,所以啦,當(dāng)然就需要先將 Tarball 解壓縮,然后到原始碼所在的目錄下進(jìn)行 makefile 的建立,再以 make 來進(jìn)行編譯與安裝的動(dòng)作啊!所以整個(gè)安裝的基礎(chǔ)動(dòng)作大多是這樣的:
            1. 將 tarball 檔案在 /usr/local/src 目錄下解壓縮;
            2. 進(jìn)入新建立的目錄底下,去查閱 INSTALL 與 README 等相關(guān)檔案內(nèi)容( 很重要的步驟! )
            3. 根據(jù) INSTALL/README 的內(nèi)容察看并安裝好一些相依的套件( 非必要 );
            4. 以自動(dòng)偵測(cè)程序( configure 或 config )偵測(cè)作業(yè)環(huán)境,并建立 Makefile 這個(gè)檔案;
            5. 以 make 這個(gè)程序并使用該目錄下的 Makefile 做為他的參數(shù)設(shè)定檔,來進(jìn)行 make ( 編譯或其它 )的動(dòng)作;
            6. 以 make 這個(gè)程序,并以 Makefile 這個(gè)參數(shù)設(shè)定檔,依據(jù) install 這個(gè)標(biāo)的( target )的指定來安裝到正確的路徑!
            注意到上面的第二個(gè)步驟,通常在每個(gè)軟件在釋出的時(shí)候,都會(huì)附上 INSTALL 或者是 README 這種檔名的說明檔,這些說明檔請(qǐng)『 確實(shí)詳細(xì)的 』閱讀過一遍,通常這些檔案會(huì)記錄這個(gè)軟件的安裝要求、軟件的工作項(xiàng)目、與軟件的安裝參數(shù)設(shè)定及技巧等,只要仔茠瑣\讀完這些檔案,基本上,要安裝好 tarball 的檔案,都不會(huì)有什么大問題啰。至于 makefile 在制作出來之后,里頭會(huì)有相當(dāng)多的標(biāo)的( target ),最常見的就是 install 與 clean 啰!通常『make clean』代表著將目標(biāo)文件( object file )清除掉,『make』則是將原始碼進(jìn)行編譯而已。注意喔!編譯完成的可執(zhí)行檔與相關(guān)的設(shè)定檔還在原始碼所在的目錄當(dāng)中喔!因此,最后要進(jìn)行『make install』來將編譯完成的所有咚咚都給他安裝到正確的路徑去,這樣就可以使用該套件啦!
             
            OK!我們底下約略提一下大部分的 tarball 軟件之安裝的指令下達(dá)方式:
            1. ./configure

            2. 這個(gè)步驟就是在建立 Makefile 這的檔案啰!通常程序開發(fā)者會(huì)寫一支 scripts 來檢查您的 Linux 系統(tǒng)、相關(guān)的套件屬性等等,這個(gè)步驟相當(dāng)?shù)闹匾驗(yàn)槲磥砟陌惭b信息都是這一步驟內(nèi)完成的!另外,這個(gè)步驟的相關(guān)信息應(yīng)該要參考一下該目錄下的 README 或 INSTALL 相關(guān)的檔案!!基本上,這個(gè)步驟完成之后會(huì)建立( 或修改 )一個(gè) Makefile ,這就是參數(shù)檔啦!
               
            3. make clean

            4. make 會(huì)讀取 Makefile 中關(guān)于 clean 的工作。這個(gè)步驟不一定會(huì)有,但是希望執(zhí)行一下!為什么呢?因?yàn)樵谶M(jìn)行編譯的時(shí)候,會(huì)產(chǎn)生一些 *.o 的檔案,例如有個(gè) abc.c 的原始碼,經(jīng)過編譯后會(huì)變成 abc.o 的檔案!我們稱這些檔案為 object file ,這些檔案如果之前已經(jīng)編譯過并留下來的話,那么這次再編譯的時(shí)候,就不會(huì)編譯該檔案,然而由于我們可能已經(jīng)修改了部分的參數(shù),因此該檔案的編譯結(jié)果事實(shí) 上應(yīng)該會(huì)有所不同!因此,為了避免前一次留下來的數(shù)據(jù)可能影響到這次編譯的結(jié)果,所以通常可以進(jìn)行一下這個(gè)步驟啰!
               
            5. make

            6. make 會(huì)依據(jù) Makefile 當(dāng)中的預(yù)設(shè)工作進(jìn)行編譯的行為!編譯的工作主要是進(jìn)行 gcc 來將原始碼編譯成為可以被執(zhí)行的 object files ,但是這些 object files 通常還需要一些函式庫(kù)之類的 link 后,才能產(chǎn)生一個(gè)完整的執(zhí)行檔!使用 make 就是要將原始碼編譯成為可以被執(zhí)行的可執(zhí)行檔,而這個(gè)可執(zhí)行檔會(huì)放置在目前所在的目錄之下,尚未被安裝到預(yù)定安裝的目錄中;
               
            7. make install

            8. 通常這就是最后的安裝步驟了,make 會(huì)依據(jù) Makefile 這個(gè)檔案里面關(guān)于 install 的項(xiàng)目,將上一個(gè)步驟所編譯完成的數(shù)據(jù)給他安裝到預(yù)定的目錄中,就完成安裝啦!
               
            9. 特別留意

            10. 請(qǐng)注意,上面的步驟是一步一步來進(jìn)行的,而 其中只要一個(gè)步驟無法成功,那么后續(xù)的步驟就完全沒有辦法進(jìn)行的! 因此,要確定每一的步驟都是成功的才可以!舉個(gè) 例子來說,萬(wàn)一今天你在 ./configure 就不成功了,那么就表示 Makefile 無法被建立起來,要知道,后面的步驟都是根據(jù) Makefile 來進(jìn)行的,既然無法建立 Makefile ,后續(xù)的步驟當(dāng)然無法成功啰!另外,如果在 make 無法成功的話,那就表示源文件無法被編譯成可執(zhí)行檔,那么 make install 主要是將編譯完成的檔案給他安裝下去的,既然都沒有成功的執(zhí)行檔了,怎么進(jìn)行安裝?所以啰,要每一個(gè)步驟都正確無誤才能往下繼續(xù)做!此外,如果安裝成功, 并且是安裝在獨(dú)立的一個(gè)目錄中,例如 /usr/local/packages 這個(gè)目錄中好了,那么您就必需手動(dòng)的將這個(gè)套件的 man page 給他放到 /etc/man.config 里面去。

            一般 Tarball 套件安裝的建議事項(xiàng)( 如何移除?升級(jí)? )
            或許您已經(jīng)發(fā)現(xiàn)了也說不定,那就是為什么前一個(gè)小節(jié)里面, Tarball 要在 /usr/local/src 里面解壓縮呢?呵呵!基本上,在預(yù)設(shè)的情況下,原本的 Linux distribution 釋出安裝的套件大多是在 /usr 里面的,而使用者自行安裝的套件則建議放置在 /usr/local 里面。這是考慮到管理使用者所安裝套件的便利性。怎么說呢?我們曉得幾乎每個(gè)套件都會(huì)提供在線說明的服務(wù),那就是 info 與 man 的功能。在預(yù)設(shè)的情況下, man 會(huì)去搜尋 /usr/local/man 里面的說明文件,因此,如果我們將套件安裝在 /usr/local 底下的話,那么自然安裝完成之后,該套件的說明文件就可以被找到了。此外,如果您所管理的主機(jī)其實(shí)是由多人共同管理的,或者是如同學(xué)校里面,一部主機(jī)是由學(xué)生管理的,但是學(xué)生總會(huì)畢業(yè)吧?所以需要進(jìn)行交接,如果大家都將套件安裝在 /usr/local 底下,那么管理上不就顯的特別的容易嗎?!所以啰,通常我們會(huì)建議大家將自己安裝的套件放置在 /usr/local 下,至于原始碼( Tarball )則建議放置在 /usr/local/src( src 為 source 的縮寫 )底下啊。
             
            再來,讓我們先來看一看 Linux distribution 預(yù)設(shè)的安裝套件的路徑會(huì)用到哪些?我們以 apache 這個(gè)軟件來說明的話( apache 是 WWW 服務(wù)器軟件,詳細(xì)的數(shù)據(jù)請(qǐng)參考服務(wù)器架設(shè)篇。您的系統(tǒng)不見得有裝這個(gè)套件 ):
            • /etc/httpd
            • /usr/lib
            • /usr/bin
            • /usr/share/man
            我們會(huì)發(fā)現(xiàn)套件的內(nèi)容大致上是擺在 etc, lib, man, bin 等目錄當(dāng)中,分別代表『設(shè)定檔、函式庫(kù)、執(zhí)行檔、在線說明檔』。好了,那么你是以 tarball 來安裝時(shí)呢?如果是放在預(yù)設(shè)的 /usr/local 里面,由于 /usr/local 原本就預(yù)設(shè)這幾個(gè)目錄了,所以你的數(shù)據(jù)就會(huì)被放在:
            • /usr/local/etc
            • /usr/local/bin
            • /usr/local/lib
            • /usr/local/man
                但是如果你每個(gè)套件都選擇在這個(gè)預(yù)設(shè)的路徑下安裝的話,那么所有的套件的檔案都將放置在這四個(gè)目錄當(dāng)中,因此,如果你都安裝在這個(gè)目錄下的話,那么未來再想要升級(jí)或移除的時(shí)候,就會(huì)比較難以追查檔案的來源啰!而如果您在安裝的時(shí)候選擇的是單獨(dú)的目錄,例如我將 apache 安裝在 /usr/local/apache 當(dāng)中,那么您的檔案目錄就會(huì)變成:
            • /usr/local/apache/etc
            • /usr/local/apache/bin
            • /usr/local/apache/lib
            • /usr/local/apache/man
                呵呵呵呵!單一套件的檔案都在同一個(gè)目錄之下,那么要移除該套件就簡(jiǎn)單的多了!只要將該目錄移除即可視為該套件已經(jīng)被移除啰!以上面為例,我想要移除 apache 只要下達(dá)『rm -rf /usr/local/apache』就算移除這個(gè)套件啦!當(dāng)然啰,實(shí)際安裝的時(shí)候還是得視該軟件的 Makefile 里頭的 install 信息才能知道到底他的安裝情況為何的。因?yàn)槔?sendmail 的安裝就很麻煩......這個(gè)方式雖然有利于套件的移除,但不曉得您有沒有發(fā)現(xiàn),我們?cè)趫?zhí)行某些指令的時(shí)候,與該指令是否在 PATH 這個(gè)環(huán)境變量所記錄的路徑有關(guān),以上面為例,我的 /usr/local/apache/bin 肯定是不在 PATH 里面的,所以執(zhí)行 apache 的指令就得要利用絕對(duì)路徑了,否則就得將這個(gè) /usr/local/apache/bin 加入 PATH 里面。另外,那個(gè) /usr/local/apache/man 也需要加入 man page 搜尋的路徑當(dāng)中啊!
                 
                除此之外, Tarball 在升級(jí)的時(shí)候也是挺困擾的,怎么說呢?我們還是以 apache 來說明好了。WWW 服務(wù)器為了考慮互動(dòng)性,所以通常會(huì)將 PHP+MySQL+Apache 一起安裝起來( 詳細(xì)的信息請(qǐng)參考服務(wù)器架設(shè)篇 ),果真如此的話,那么每個(gè)套件在安裝的時(shí)候『都有一定的順序與程序!』因?yàn)樗麄內(nèi)咧g具有相關(guān)性,所以安裝時(shí)必需要三者同時(shí)考慮到他們的函式庫(kù)與相關(guān)的編譯參數(shù)。那么如果今天我只要升級(jí) PHP 呢?有的時(shí)候因?yàn)橹挥猩婕皠?dòng)態(tài)函式庫(kù)的升級(jí),那么我只要升級(jí) PHP 即可!其它的部分或許影響不大。但是如果今天 PHP 需要重新編譯的模塊比較多,那么可能會(huì)連帶的,連 Apache 這個(gè)程序也需要重新編譯過才行!真是有點(diǎn)給他頭痛的!沒辦法啦!使用 tarball 確實(shí)有他的優(yōu)點(diǎn)啦,但是在這方面,確實(shí)也有他一定的傷腦筋程度。
                 
                由于 Tarball 在升級(jí)與安裝上面具有這些特色,亦即 Tarball 在反安裝上面具有比較高的難度( 如果您沒有好好規(guī)劃的話~ ),所以,為了方便 Tarball 的管理,通常我們會(huì)這樣建議使用者:
                 
                1. 最好將 tarball 的原始數(shù)據(jù)解壓縮到 /usr/local/src 當(dāng)中;
                2. 安裝時(shí),最好安裝到 /usr/local 這個(gè)預(yù)設(shè)路徑下;
                3. 考慮未來的反安裝步驟,最好可以將每個(gè)套件單獨(dú)的安裝在 /usr/local 底下,例如安裝 rp-pppoe-2.6.tar.gz 時(shí),則可以指定該套件需要安裝于 /usr/local/rp-pppoe 當(dāng)中,如此一來,該套件會(huì)將所有的數(shù)據(jù)都寫入 /usr/local/rp-pppoe 當(dāng)中,因此,未來如果要移除該套件,只要將該目錄刪除即可視為成功的移除了!
                4. 不過單獨(dú)安裝某個(gè)套件在某一特定路徑下的作法,會(huì)導(dǎo)致當(dāng)有 man page 的時(shí)候,使用預(yù)設(shè)的 MANPATH 會(huì)找不到相關(guān)的說明檔案內(nèi)容。這個(gè)時(shí)候就必須要將 man page 的路徑加到 /etc/man.config 檔案中了!否則使用 man 也查詢不到指令的使用方法的。以上面的例子為例,如果是安裝了 /usr/local/rp-pppoe 當(dāng)中,通常 man page 會(huì)放在 /usr/local/rp-pppoe/man 當(dāng)中,所以,您就必需要在 /etc/man.config 里面差不多 40~50 行左右的地方,加入底下這一行:
                  1. MANPATH /usr/local/rp-pppoe/man
                  這樣就可以使用 man 來查詢資料啰!

            一個(gè)簡(jiǎn)單的范例、利用 ntp 來示范
            讀萬(wàn)卷書不如行萬(wàn)里路啊!所以當(dāng)然我們就來給他測(cè)試看看,看您是否真的了解了如何利用 Tarball 來安裝軟件呢?!我們利用時(shí)間服務(wù)器 ntp-4.1.2 這個(gè)套件來測(cè)試安裝看看。先請(qǐng)到 http://www.ntp.org/downloads.html 這個(gè)目錄去下載檔案,(您也可以下載比較新的檔案來測(cè)試的啦!)或者直接到鳥哥的網(wǎng)站下載:
            http://linux.vbird.org/download/books/basic/source_code/ntp-4.1.2.tar.gz
            假設(shè)我對(duì)這個(gè)套件的要求是這樣的:
            • 假設(shè) ntp-4.1.2.tar.gz 這個(gè)檔案放置在 /root 這個(gè)目錄下;
            • 原始碼請(qǐng)解開在 /usr/local/src 底下;
            • 我要安裝到 /usr/local/ntp 這個(gè)目錄中;
            那么您可以依照底下的步驟來安裝測(cè)試看看( 如果可以的話,請(qǐng)您不要參考底下的文件數(shù)據(jù),先自行安裝過一遍這個(gè)軟件,然后再來對(duì)照一下鳥哥的步驟喔! )。
             
            # 1. 解壓縮,并閱讀一下 ntp 底下的 README 與 INSTALL:?
            [root@test root]# cd /usr/local/src?
            [root@test src]# tar -zxvf /root/ntp-4.1.2.tar.gz?
            # 這個(gè)步驟會(huì)讓原始碼解開成為 /usr/local/src/ntp-4.1.2 這個(gè)目錄
             
            # 2. 進(jìn)入原始碼所在目錄,并且查閱如何安裝的技巧:
            [root@test src]# cd ntp-4.1.2?
            [root@test ntp-4.1.2]# vi INSTALL ( 或 vi README)?
             
            # 3. 開始設(shè)定參數(shù)、編譯與安裝:
            [root@test ntp-4.1.2]# ./configure --help | more?
            # 上面這個(gè)動(dòng)作可以察看一下可用的參數(shù)!?
             
            [root@test ntp-4.1.2]# ./configure --prefix=/usr/local/ntp? \?
            >? --enable-all-clocks --enable-parse-clocks?
            checking for gcc... (cached) gcc
            checking whether we are using the GNU C compiler... (cached) yes
            checking whether gcc accepts -g... (cached) yes
            .....(略)....
            configure: creating ./config.status
            config.status: creating Makefile
            # 一般來說 configure 設(shè)定參數(shù)較重要的就是那個(gè) --prefix=/path 了,
            # --prefix 后面接的路徑就是『這個(gè)軟件未來要安裝到那個(gè)目錄去?』
            # 如果您沒有指定 --prefix=/path 這個(gè)參數(shù),通常預(yù)設(shè)參數(shù)就是 /usr/local
            # 至于其它的參數(shù)意義就得要參考 ./configure --help 了!
            # 這個(gè)動(dòng)作完成之后會(huì)產(chǎn)生 makefile 或 Makefile 這個(gè)檔案
            # 當(dāng)然啦,這個(gè)偵測(cè)檢查的過程會(huì)顯示在屏幕上,特別留意關(guān)于 gcc 的檢查
            # 還有最重要的是最后需要成功的建立起 Makefile 才行!(上面最后一行)
             
            [root@test ntp-4.1.2]# make clean ; make?
            [root@test ntp-4.1.2]# make check
            [root@test ntp-4.1.2]# make install
            # 將數(shù)據(jù)給他安裝在 /usr/local/ntp 底下
             
            整個(gè)動(dòng)作就這么簡(jiǎn)單,您完成了嗎?!完成之后到 /usr/local/ntp 您發(fā)現(xiàn)了什么?!

            利用 patch 更新原始碼
                我們?cè)谇把岳锩娼榻B了為何需要進(jìn)行套件的升級(jí),這是很重要的喔!那假如我是以 Tarball 來進(jìn)行某個(gè)套件的安裝,那么是否當(dāng)我要升級(jí)這個(gè)套件時(shí),就得要下載這個(gè)套件的完整全新的 Tarball 呢?舉個(gè)例子來說,鳥哥有個(gè)討論區(qū)在 http://phorum.vbird.org 這個(gè)網(wǎng)址,這個(gè)討論區(qū)是以 phpBB 這個(gè)套件來架設(shè)的,而鳥哥的討論區(qū)版本為 phpbb2.0.1.tar.gz ,目前( 2004/04/10 )最新釋出的版本則是 phpbb2.0.8.tar.gz 。那我是否需要下載全新的 phpbb2.0.8.tar.gz 這個(gè)檔案來更新原本的舊程序呢?
                 
                事實(shí)上,當(dāng)我們發(fā)現(xiàn)一些套件的漏洞,通常是某一段程序代碼寫的不好所致。因此,所謂的『更新原始碼』常常是只有更改部分檔案的小部分內(nèi)容而已。既然 如此的話,那么我們是否可以就那些被更動(dòng)的檔案來進(jìn)行修改就可以咯?也就是說,舊版本到新版本間沒有更動(dòng)過的檔案就不要理他,僅將有修訂過的檔案部分來處 理即可。這有什么好處呢?首先,沒有更動(dòng)過的檔案的目標(biāo)文件( object file )根本就不需要重新編譯,而且有更動(dòng)過的檔案又可以利用 make 來自動(dòng) update ( 更新 ),如此一來,呵呵!我們?cè)鹊脑O(shè)定( makefile 檔案里面的規(guī)則 )將不需要重新改寫或偵測(cè)!呵呵!可以節(jié)省很多寶貴的時(shí)間呢( 例如后續(xù)章節(jié)會(huì)提到的核心的編譯! )
                 
                從上面的說明當(dāng)中,我們可以發(fā)現(xiàn),如果可以將舊版的原始碼數(shù)據(jù)改寫成新版的版本,那么就能直接編譯了,而不需要將全部的新版 Tarball 重新下載一次呢!可以節(jié)省頻寬與時(shí)間說!那么如何改寫原始碼?難道要我們一個(gè)檔案一個(gè)檔案去參考然后修訂嗎?當(dāng)然沒有這么沒人性!我們?cè)?a >正規(guī)表示法的時(shí)候有提到一個(gè)比對(duì)兩個(gè)檔案的指令,那就是 diff ,這個(gè)指令可以將『兩個(gè)檔案之間的差異性列出來』呢!那我們也知道新舊版本的檔案之間,其實(shí)只有修改一些程序而已,那么我們可以透過 diff 比對(duì)出新舊版本之間的文字差異,然后再以相關(guān)的指令來將舊版的檔案更新嗎?!呵呵!當(dāng)然可以啦!那就是 patch 這個(gè)指令啦!很多的套件開發(fā)商在更新了原始碼之后,幾乎都會(huì)釋出所謂的 patch file,也就是直接將原始碼 update 而已的一個(gè)方式喔!我們底下以一個(gè)簡(jiǎn)單的范例來說明給您了解喔!
                 
                假設(shè)我們有兩個(gè)檔案,分別是 expatch.old 與 expatch.new ,他們的內(nèi)容是這樣的:
                 
                [guest@test guest]# vi expatch.old
                echo "check your postfix's body and header drop settings"
                echo "postmap -q - regexp:header_checks < header_checks"
                postmap -q - regexp:header_checks < header_checks
                echo "postmap -q - regexp:body_checks < body_checks"
                postmap -q - regexp:body_checks < body_checks

                [guest@test guest]# vi expatch.new
                echo "check your postfix's body and header drop settings"
                echo "postmap -q - regexp:header_checks < header_checks This's right"
                postmap -q - regexp:header_checks < header_checks
                echo "postmap -q - regexp:body_checks < body_checks This's right"
                postmap -q - regexp:body_checks < body_checks

                 
                兩個(gè)檔案的不同點(diǎn)在于:
                 
                [guest@test guest]# diff expatch.old expatch.new
                2c2
                < echo "postmap -q - regexp:header_checks < header_checks"
                ---
                > echo "postmap -q - regexp:header_checks < header_checks This's right"
                4c4
                < echo "postmap -q - regexp:body_checks < body_checks"
                ---
                > echo "postmap -q - regexp:body_checks < body_checks This's right"
                 
                上面顯示出兩個(gè)檔案的不同點(diǎn),詳細(xì)的意義請(qǐng)參考正規(guī)表示法那個(gè)章節(jié)的介紹。 好了,假如我以『 diff -c expatch.old expatch.new 』以及上面顯示的信息,做成一個(gè)檔案,內(nèi)容是這樣的:
                 
                [guest@test guest]# vi expatch.patch
                *** expatch.old 2004-04-09 14:22:49.000000000 +0800
                --- expatch.new 2004-04-09 14:23:18.000000000 +0800
                2c2
                < echo "postmap -q - regexp:header_checks < header_checks"
                ---
                > echo "postmap -q - regexp:header_checks < header_checks This's right"
                4c4
                < echo "postmap -q - regexp:body_checks < body_checks"
                ---
                > echo "postmap -q - regexp:body_checks < body_checks This's right"
                 
                注意到,這個(gè)檔案的第一行顯示出舊版本的文件名,而第二行則為新版本的檔名與時(shí)間,第三行以后則是兩個(gè)檔案的差異性。那么我們將以 patch 來進(jìn)行更新,將 expatch.old 更新到 expatch.new 看看。patch 的基本語(yǔ)法是這樣的:
                 
                  patch -p數(shù)字 < patch_file
                 
                特別留意那個(gè) -p數(shù)字,那是與 patch_file 里面列出的文件名有關(guān)的信息。假如在 patch_file 第一行寫的是這樣:
                 
                  *** /home/guest/example/expatch.old
                 
                那么當(dāng)我下達(dá)『 patch -p0 < patch_file 』時(shí),則更新的檔案是『 /home/guest/example/expatch.old 』,如果『 patch -p1 < patch_file』,則更新的檔案為『home/guest/example/expatch.od』,如果『patch -p4 < patch_file』則更新『expatch.old』,也就是說, -pxx 那個(gè) xx 代表『拿掉幾個(gè)斜線(/)』的意思!這樣可以理解了嗎?!好了,那么我要開始來更新我的 expatch.old 了,可以這樣搞定:
                 
                [guest@test guest]# patch -p0 < expatch.patch
                # 注意喔,這個(gè)時(shí)候我的工作目錄底下會(huì)存在 expatch.old 才對(duì)!
                # 然后立刻察看一下,您會(huì)發(fā)覺, expatch.new 與 expatch.old 變成一模一樣的了!
                 
                很容易了解吧!上面三個(gè)檔案您可以在底下的網(wǎng)址取得: 加油的啦!另外,如果您是以 patch 更新原始碼,那么記得,您可能必須要重新編譯,并且重新 install 才算成功更新喔!并不是 patch 就好了!因?yàn)?patch 的功能主要僅只是更新原始碼檔案而已!切記切記
                 
                鳥哥提問題:如果我有一個(gè)很舊版的套件,這個(gè)套件已經(jīng)更新到很新的版本,例如核心,那么我可以使用 patch file 來更新嗎?
                 
                  這個(gè)問題挺有趣的,首先,您必須要確定舊版本與新版本之間『確實(shí)有釋出 patch file 』才行,以 kernel 2.2.xx 及 2.4.xx 來說,這兩者基本上的架構(gòu)已經(jīng)不同了,所以兩者間是無法以 patch file 來更新的。不過, 2.4.xx 與 2.4.yy 就可以更新了。不過,因?yàn)?kernel 每次推出的 patch 檔案都僅針對(duì)前一個(gè)版本而已,所以假設(shè)要由 kernel 2.4.20 升級(jí)到 2.4.26 ,就必須要使用 patch 2.4.21, 2.4.22, 2.4.23, 2.4.24, 2.4.25, 2.4.26 六個(gè)檔案來『依序更新』才行喔!當(dāng)然,如果有朋友幫您比對(duì)過 2.4.20 與 2.4.26 ,那您自然就可以使用該 patch file 來直接一次更新啰!

            函式庫(kù)管理:
              在我們的 Linux 操作系統(tǒng)當(dāng)中,函式庫(kù)是很重要的一個(gè)項(xiàng)目。因?yàn)楹芏嗟奶准g都會(huì)互相取用彼此提供的函式庫(kù)來進(jìn)行特殊功能的運(yùn)作,例如很多需要驗(yàn)證身份的程序都習(xí)慣利用 PAM 這個(gè)模塊提供的驗(yàn)證機(jī)制來實(shí)作,而很多網(wǎng)絡(luò)聯(lián)機(jī)機(jī)制則習(xí)慣利用 SSL 函式庫(kù)來進(jìn)行聯(lián)機(jī)加密的機(jī)制。所以說,函式庫(kù)的利用是很重要的。不過,函式庫(kù)又依照是否被編譯到程序內(nèi)部而分為動(dòng)態(tài)與靜態(tài)函式庫(kù),這兩者之間有何差異?哪 一種函式庫(kù)比較好?底下我們就來談一談先!
               

              動(dòng)態(tài)與靜態(tài)函式庫(kù)
            首先我們要知道的是,函式庫(kù)的類型有哪些?依據(jù)函式庫(kù)被使用的類型而分為兩大類,分別是靜態(tài)( Static )與動(dòng)態(tài)( Dynamic )函式庫(kù)兩類。底下我們來談一談這兩種類行的函式庫(kù)吧!
            • 靜態(tài)函式庫(kù)
              • 附檔名:這類的函式庫(kù)通常附檔名為 libxxx.a 的類型;
              • 編譯行為:這一類型的函式庫(kù)在被使用到程序當(dāng)中的時(shí)候,都是整個(gè)函式庫(kù)的所有數(shù)據(jù)被整合到執(zhí)行文件當(dāng)中,也就是說,當(dāng)我們?cè)谶M(jìn)行編譯的動(dòng)作時(shí),這個(gè)函式庫(kù)會(huì)被加入到執(zhí)行檔內(nèi),所以利用靜態(tài)函式庫(kù)編譯成的檔案會(huì)比較大一些喔
              • 獨(dú)立執(zhí)行的狀態(tài):這類函式庫(kù)最大的優(yōu)點(diǎn),就是編譯成功的可執(zhí)行檔可以獨(dú)立執(zhí)行,而不需要再向外部要求讀取函式庫(kù)的內(nèi)容( 請(qǐng)參照動(dòng)態(tài)函式庫(kù)的說明 )。
              • 升級(jí)難易度:雖然執(zhí)行檔可以獨(dú)立執(zhí)行,然而當(dāng)函式庫(kù)升級(jí)的時(shí)候,由于我們的執(zhí)行檔取用的是之前版本的函式庫(kù),所以當(dāng)函式庫(kù)升級(jí)后,連執(zhí)行檔也需要重新編譯過一次,才能將新的函式庫(kù)整合到執(zhí)行檔當(dāng)中。
               
            • 動(dòng)態(tài)函式庫(kù)
              • 附檔名:這類函式庫(kù)通常附檔名為 libxxx.so 的類型;
              • 編譯行為:動(dòng)態(tài)函式庫(kù)與靜態(tài)函式庫(kù)的編譯行為差異挺大的,靜態(tài)函式庫(kù)是整個(gè)被編譯到執(zhí)行文件當(dāng)中,但是動(dòng)態(tài)函式庫(kù)在編譯的時(shí)候,在程序里面只有一個(gè)『指向( Pointer )』的位置而已。也就是說,動(dòng)態(tài)函式庫(kù)的內(nèi)容并沒有被整合到執(zhí)行檔當(dāng)中,而是當(dāng)執(zhí)行檔要使用到函式庫(kù)的機(jī)制時(shí),程序才會(huì)去讀取函式庫(kù)來使用。由于執(zhí)行文件當(dāng)中僅具有指向動(dòng)態(tài)函式庫(kù)所在的指標(biāo)而已,并不包含函式庫(kù)的內(nèi)容,所以他的檔案會(huì)比較小一點(diǎn)
              • 獨(dú)立執(zhí)行的狀態(tài):這類型的函式庫(kù)不能被獨(dú)立執(zhí)行,因?yàn)楫?dāng)我們使用到函式庫(kù)的機(jī)制時(shí),程序會(huì)去讀取函式庫(kù),所以函式庫(kù)『必須要存在』才行,而且,函式庫(kù)的『所在目錄也不能改變』,因?yàn)槲覀兊目蓤?zhí)行檔里面僅有『指標(biāo)』亦即當(dāng)要取用該動(dòng)態(tài)函式庫(kù)時(shí),程序會(huì)主動(dòng)去某個(gè)路徑下讀取,呵呵!所以動(dòng)態(tài)函式庫(kù)可不能隨意移動(dòng)或刪除,會(huì)影響很多相依的程序軟件喔!
              • 升級(jí)難易度:雖然這類型的執(zhí)行檔無法獨(dú)立運(yùn)作,然而由于是具有指向的功能,所以,當(dāng)函式庫(kù)升級(jí)后,執(zhí)行檔根本不需要進(jìn)行重新編譯的行為,因?yàn)閳?zhí)行檔會(huì)直接指向新的函式庫(kù)檔案( 前提是函式庫(kù)新舊版本的檔名相同喔! )。
                在目前的 Linux distribution 當(dāng)中,我們比較傾向于使用動(dòng)態(tài)函式庫(kù),因?yàn)槿缤厦嫣岬降淖钪匾囊稽c(diǎn),就是函式庫(kù)的升級(jí)方便!由于 Linux 系統(tǒng)里面的套件相依性太復(fù)雜了,如果使用太多的靜態(tài)函式庫(kù),那么升級(jí)某一個(gè)函式庫(kù)時(shí),都會(huì)對(duì)整個(gè)系統(tǒng)造成很大的沖擊!因?yàn)槠渌嘁赖膱?zhí)行檔也要同時(shí)重新編譯啊!這個(gè)時(shí)候動(dòng)態(tài)函式庫(kù)可就有用多了,因?yàn)橹灰獎(jiǎng)討B(tài)函式庫(kù)升級(jí)就好,其它的套件根本無須變動(dòng)。
                 
                那么這些函式庫(kù)放置在哪里呢?絕大多數(shù)的函式庫(kù)都放置在:
                • /usr/lib
                • /lib
                此外,Linux 系統(tǒng)里面很多的函式庫(kù)其實(shí) kernel 就提供了,那么 kernel 的函式庫(kù)放在哪里?呵呵!就是在 /lib/modules 里面啦!里面的數(shù)據(jù)可多著呢!不過要注意的是,不同版本的核心提供的函式庫(kù)差異性是挺大的,所以 kernel 2.2.xx 版本的系統(tǒng)不要想將核心換成 2.4.xx 喔!很容易由于函式庫(kù)的不同而導(dǎo)致很多原本可以執(zhí)行的軟件套件無法順利運(yùn)作呢!更多的核心相關(guān)說明我們?cè)诤竺鏁?huì)繼續(xù)的給他介紹的。
               

              ldconfig 與 /etc/ld.so.conf
               
                在了解了動(dòng)態(tài)與靜態(tài)函式庫(kù),也知道我們目前的 Linux 大多是將函式庫(kù)做成動(dòng)態(tài)函式庫(kù)之后,再來要知道的就是,那有沒有辦法增加函式庫(kù)的讀取效能?!我們知道內(nèi)存的存取速度是硬盤的好幾倍,所以,如果我們將常用到的動(dòng)態(tài)函式庫(kù)先加載內(nèi)存當(dāng)中( 快取, cache ),如此一來,當(dāng)軟件套件要取用動(dòng)態(tài)函式庫(kù)時(shí),就不需要重從頭由硬盤里面讀出啰!這樣不就可以增進(jìn)動(dòng)態(tài)函式庫(kù)的讀取速度?沒錯(cuò),是這樣的!這個(gè)時(shí)候就需要 ldconfig 與 /etc/ld.so.conf 的協(xié)助了。
                 
                如何將動(dòng)態(tài)函式庫(kù)加載高速緩存( cache )當(dāng)中呢?
                 
                1. 首先,我們必須要在 /etc/ld.so.conf 里面寫下『想要讀入高速緩存當(dāng)中的動(dòng)態(tài)函式庫(kù)所在的目錄』,注意喔,是目錄而不是檔案;
                2. 接下來則是利用 ldconfig 這個(gè)執(zhí)行檔將 /etc/ld.so.conf 的資料讀入快取當(dāng)中;
                3. 同時(shí)也將數(shù)據(jù)記錄一份在 /etc/ld.so.cache 這個(gè)檔案當(dāng)中吶!
                 
                事實(shí)上, ldconfig 還可以用來判斷動(dòng)態(tài)函式庫(kù)的連結(jié)信息呢!趕緊利用 Red Hat 9 來測(cè)試看看。假設(shè)我還想要將我的 MySQL 函式庫(kù)加入到快取當(dāng)中:
                  
                [root@test root]# ldconfig [-f conf] [-C cache] [-p]
                參數(shù)說明:
                -f conf :那個(gè) conf 指的是某個(gè)文件名稱,也就是說,使用 conf 作為 libarary?
                     函式庫(kù)的取得路徑,而不以 /etc/ld.so.conf 為默認(rèn)值
                -C cache:那個(gè) cache 指的是某個(gè)文件名稱,也就是說,使用 cache 作為快取暫存
                     的函式庫(kù)資料,而不以 /etc/ld.so.cache 為默認(rèn)值
                -p   :列出目前有的所有函式庫(kù)資料內(nèi)容(在 /etc/ld.so.cache 內(nèi)的資料!)
                范例:
                [root@test root]# vi /etc/ld.so.conf
                /usr/kerberos/lib
                /usr/X11R6/lib
                /usr/lib/mysql? <==這一行是新加入的喔!
                 
                [root@test root]# ldconfig
                # 畫面上不會(huì)顯示任何的信息,不要太緊張!正常的!
                 
                [root@test root]# ldconfig -p
                680 libs found in cache `/etc/ld.so.cache'
                ??????? libzvt.so.2 (libc6) => /usr/lib/libzvt.so.2
                ??????? libz.so.1 (libc6) => /usr/lib/libz.so.1
                ??????? libz.so (libc6) => /usr/lib/libz.so
                ??????? libx11globalcomm.so.1 (libc6) => /usr/lib/libx11globalcomm.so.1
                ........(略).....
                 
                透過上面的動(dòng)作,我們可以將 MySQL 的相關(guān)函式庫(kù)給他讀入快取當(dāng)中,這樣可以加快函式庫(kù)讀取的效率呢!在某些時(shí)候,您可能會(huì)自行加入某些 Tarball 安裝的動(dòng)態(tài)函式庫(kù),而您想要讓這些動(dòng)態(tài)函式庫(kù)的相關(guān)連結(jié)可以被讀入到快取當(dāng)中,這個(gè)時(shí)候您可以將動(dòng)態(tài)函式庫(kù)所在的目錄名稱寫入 /etc/ld.so.conf 當(dāng)中,然后執(zhí)行 ldconfig 就可以啦!
                ?

              ldd
                 
                說了這么多,那么我如何判斷某個(gè)可執(zhí)行的 binary 檔案含有什么動(dòng)態(tài)函式庫(kù)呢?很簡(jiǎn)單,利用 ldd 就可以曉得了!例如我想要知道 /usr/bin/passwd 這個(gè)程序含有的動(dòng)態(tài)函式庫(kù)有哪些,可以這樣做:
                 
                [root@test root]# ldd [-vdr] [filename]
                參數(shù)說明:
                -v :列出所有內(nèi)容信息;
                -d :重新將數(shù)據(jù)有遺失的 link 點(diǎn)秀出來!
                -r :將 ELF 有關(guān)的錯(cuò)誤內(nèi)容秀出來!
                范例:
                [root@test root]# ldd /usr/bin/passwd
                ??????? libuser.so.1 => /usr/lib/libuser.so.1 (0x40021000)
                ....(略)....
                ??????? libpam.so.0 => /lib/libpam.so.0 (0x40107000)
                ....(略)....
                # 我們前言的部分不是一直提到 passwd 有使用到 pam 的模塊嗎?!怎么知道?
                # 利用 ldd 察看一下這個(gè)檔案,看到 libpam.so 了吧?這就是 pam 提供的函式庫(kù)
                 
                [root@test root]#? ldd /lib/libc.so.6
                ??????? /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
                 
                [root@pc510 vbird]# ldd -v /lib/libc.so.6
                ??????? /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

                ??????? Version information:
                ??????? /lib/libc.so.6:
                ??????????????? ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2
                ??????????????? ld-linux.so.2 (GLIBC_2.0) => /lib/ld-linux.so.2
                ??????????????? ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2

                 
                未來如果您常常升級(jí)安裝 RPM 的套件時(shí)( 下一章節(jié)會(huì)介紹 ),應(yīng)該常常會(huì)發(fā)現(xiàn)那個(gè)『相依屬性』的問題吧!?沒錯(cuò)!我們可以先以 ldd 來視察『相依函式庫(kù)』之間的相關(guān)性!以先取得了解!例如上面的例子中,我們檢查了 libc.so.6 這個(gè)在 /lib 當(dāng)中的函式庫(kù),結(jié)果發(fā)現(xiàn)他其實(shí)還跟 ld-linux.so.2 有關(guān)!所以我們就需要來了解一下,那個(gè)檔案到底是什么套件的函式庫(kù)呀!?使用 -v 這個(gè)參數(shù)還可以得知該函式庫(kù)來自于哪一個(gè)套件!像上面的數(shù)據(jù)中,就可以得到該 libc.so.6 其實(shí)可以支持 GLIBC_2.1 等的版本!

            檢驗(yàn)軟件正確性
            前面提到很多升級(jí)與安裝需要注意的事項(xiàng),因?yàn)槲覀冃枰朔芏嗟某绦蚵┒矗孕枰巴? Linux distribution 或者是某些套件開發(fā)商的網(wǎng)站,下載最新并且較安全的檔案來安裝才行。好了,那么『有沒有可能我們下載的檔案本身就有問題?』是可能的!因?yàn)轳斂藷o所不在,很多的套件開發(fā)商已經(jīng)公布過他們的網(wǎng)頁(yè)所放置的檔案曾經(jīng)被竄改過!那怎么辦?連下載原版的數(shù)據(jù)都可能有問題了?難道沒有辦法判斷檔案的正確性嗎?!
             
            這個(gè)時(shí)候我們就要透過每個(gè)檔案獨(dú)特的指紋驗(yàn)證數(shù)據(jù)了!因?yàn)槊總€(gè)檔案的內(nèi)容與檔案大小都不相同,所以如果一個(gè)檔案被修改之后,必然會(huì)有部分的信息不一樣!利用這個(gè)咚咚,我們可以使用 MD5 這個(gè)指紋驗(yàn)證機(jī)制來判斷該檔案有沒有被更動(dòng)過!舉個(gè)例子來說,中山大學(xué)提供的 Red Hat 9 原版光盤下載點(diǎn)( http://ftp.nsysu.edu.tw/Linux/RedHat/linux/9/en/iso/i386/ )同時(shí)提供了 Red Hat 9 所有光盤 ISO 檔案的 MD5 編碼,透過這個(gè)編碼的比對(duì),我們就可以曉得下載的檔案是否有問題。那么萬(wàn)一 Red Hat 提供的光盤映象文件(image)被下載之后,讓有心人士偷偷修改過,再轉(zhuǎn)到 Internet 上面流傳,那么你下載的這個(gè)檔案偏偏不是原廠提供的,呵呵!你能保證該檔案的內(nèi)容完全沒有問題嗎?!當(dāng)然不能對(duì)不對(duì)?!是的,這個(gè)時(shí)候就有 md5sum 這個(gè)檔案指紋的咚咚出現(xiàn)啦!說說他的用法吧!

            md5sum
              我們以 Red Hat 在 2004 年發(fā)布的一則程序臭蟲修訂程序?yàn)槔?
                 
              這個(gè) grep-2.5.1-7.8.i386.rpm 的檔案他的 MD5 指紋編碼是:『5a0c3fcfcd4c3f937644b8cd71a0cf89』,如果您下載了這個(gè)檔案,并且執(zhí)行底下的指令,應(yīng)該得到相同的指紋碼的:
               
              [root@test root]# md5sum [-bct] filename
              [root@test root]# md5sum [--status|--warn] --check filename
              參數(shù)說明:
              -b :使用 binary 的讀檔方式,預(yù)設(shè)為 Windows/DOS 檔案型態(tài)的讀取方式;
              -c :檢驗(yàn) md5sum 檔案指紋;
              -t :以文字型態(tài)來讀取 md5sum 的檔案指紋。
              范例:
              [root@test root]# md5sum grep-2.5.1-7.8.i386.rpm
              5a0c3fcfcd4c3f937644b8cd71a0cf89? grep-2.5.1-7.8.i386.rpm
              # 看!顯示的編碼是否與上面相同呢?!趕緊測(cè)試看看!
               
              一般而言,每個(gè)系統(tǒng)里面的檔案內(nèi)容大概都不相同,例如你的系統(tǒng)中的 /etc/passwd 這個(gè)登入信息文件與我的一定不一樣,因?yàn)槲覀兊氖褂谜吲c密碼、 Shell 及家目錄等大概都不相同,所以由 md5sum 這個(gè)檔案指紋分析程序所自行計(jì)算出來的指紋表當(dāng)然就不相同啰!
               
              好了,那么如何使用這個(gè)東西呢?基本上,您必須要在您的 Linux 系統(tǒng)上為您的這些重要的檔案進(jìn)行指紋數(shù)據(jù)庫(kù)的建立( 好像在做戶口調(diào)查! ),將底下這些檔案建立數(shù)據(jù)庫(kù):
               
              • /etc/passwd
              • /etc/shadow( 假如你不讓使用者改密碼了 )
              • /etc/group
              • /usr/bin/passwd
              • /sbin/portmap
              • /bin/login ( 這個(gè)也很容易被駭! )
              • /bin/ls
              • /bin/ps
              • /usr/bin/top
               
              等等,這幾個(gè)檔案最容易被修改了!因?yàn)楹芏嗄抉R程序執(zhí)行的時(shí)候,還是會(huì)有所謂的『執(zhí)行序, PID』為了怕被 root 追查出來,所以他們都會(huì)修改這些檢查排程的檔案,如果你可以替這些檔案建立指紋數(shù)據(jù)庫(kù)( 就是使用 md5sum 檢查一次,將該檔案指紋記錄下來,然后常常以 shell script 的方式由程序自行來檢查指紋表是否不同了! ),那么對(duì)于檔案系統(tǒng)會(huì)比較安全啦!!

            重點(diǎn)回顧
            • 原始碼其實(shí)大多是純文字文件,需要透過編譯器的編譯動(dòng)作后,才能夠制作出 Linux 系統(tǒng)能夠認(rèn)識(shí)的可執(zhí)行的 binary file ;
            • 在 Linux 系統(tǒng)當(dāng)中,最標(biāo)準(zhǔn)的 C 語(yǔ)言編譯器為 gcc ;
            • 在編譯的過程當(dāng)中,可以藉由其它套件提供的函式庫(kù)來使用該套件的相關(guān)機(jī)制與功能;
            • 為了簡(jiǎn)化編譯過程當(dāng)中的復(fù)雜的指令輸入,可以藉由 make 與 makefile 規(guī)則定義,來簡(jiǎn)化程序的更新、編譯與連結(jié)等動(dòng)作;
            • Tarball 為使用 tar 與 gzip 壓縮功能所打包與壓縮的,具有原始碼程序文件的檔案;
            • 一般而言,要使用 Tarball 管理 Linux 系統(tǒng)上的套件,最好需要 gcc, make, autoconfig, kernel source, kernel header 等前驅(qū)套件才行,所以在安裝 Linux 之初,最好就能夠選擇 Software development 以及 kernel development 之類的群組;
            • 函式庫(kù)有動(dòng)態(tài)函式庫(kù)與靜態(tài)函式庫(kù),動(dòng)態(tài)函式庫(kù)在升級(jí)上具有較佳的優(yōu)勢(shì)。動(dòng)態(tài)函式庫(kù)的附檔名為 *.so 而靜態(tài)則是 *.a ;
            • patch 的主要功能在更新原始碼,所以更新原始碼之后,還需要進(jìn)行重新編譯的動(dòng)作才行;
            • 可以利用 ldconfig 與 /etc/ld.so.conf 來制作動(dòng)態(tài)函式庫(kù)的連結(jié)與快取!
            • 透過 MD5 的編碼可以判斷下載的檔案是否為原本廠商所釋出的檔案。

            參考資源
            如果您對(duì)于程序的開發(fā)相當(dāng)?shù)挠信d趣,那么真的建議挑這個(gè)跨平臺(tái)的 C 語(yǔ)言來學(xué)習(xí)!

            課后練習(xí)

            原始碼與 Tarball 套件管理員

            2002/08/21: 第一次完成
            2003/02/11:重新編排與 加入 FAQ
            2004/03/25:原本是 Tarball 與 RPM ,本日開始將 Tarball 與 RPM? 分開說明與講解(后續(xù)會(huì)花好幾天喔!),最重要的是 Source code 的說明,并提到相關(guān)的 gcc compile 功能等等!
            2004/04/10:經(jīng)歷了當(dāng)兵中的無奈生活,終于將這篇給他完工了~

            posted on 2007-09-29 02:07 旅途 閱讀(488) 評(píng)論(0)  編輯 收藏 引用 所屬分類: Linux開發(fā)

            久久99精品久久久久久不卡| 2021久久精品国产99国产精品| 久久夜色精品国产噜噜噜亚洲AV | 亚洲国产精品一区二区三区久久| 精品久久久久久国产免费了| 三级片免费观看久久| 99久久精品免费看国产一区二区三区| 亚洲va久久久噜噜噜久久男同| 99久久国产综合精品麻豆| 国产精品成人无码久久久久久 | 久久久国产一区二区三区| 97久久国产露脸精品国产| 国内精品久久久久影院一蜜桃| 久久99精品久久久久久不卡| 久久久久99精品成人片试看| 久久香蕉国产线看观看猫咪?v| 久久精品国产亚洲AV无码偷窥| 久久久久国产成人精品亚洲午夜| 97久久国产综合精品女不卡| 久久久国产精品| 国内精品久久久久久久久| 久久综合狠狠综合久久| 中文成人久久久久影院免费观看 | 久久91精品国产91| 情人伊人久久综合亚洲| 久久人人爽爽爽人久久久| 久久婷婷是五月综合色狠狠| 精品久久国产一区二区三区香蕉| 99久久久国产精品免费无卡顿| 狠狠色噜噜色狠狠狠综合久久| 久久久久女教师免费一区| 91精品观看91久久久久久| 国产精品久久久久久影院| 久久久久久久久无码精品亚洲日韩 | 久久久久99精品成人片试看| 精品国产乱码久久久久久人妻| 久久夜色撩人精品国产| 久久精品综合一区二区三区| 久久国产香蕉一区精品| 色诱久久av| 狠狠色综合网站久久久久久久高清|