1. 什么是開放源碼、編譯程序與可執(zhí)行文件
我們使用特定編程語(yǔ)言(如C或Java等),編寫的純文本文件即為源碼文件。在完成源碼文件的編寫之后,再通過編譯程序?qū)⒃创a文件編譯成操作系統(tǒng)看得懂的二進(jìn)制可執(zhí)行文件。
在Linux上最標(biāo)準(zhǔn)的程序語(yǔ)言為C,所以我們使用C語(yǔ)法寫完源碼(以*.c擴(kuò)展名形式存在)后,以Linux上標(biāo)準(zhǔn)C語(yǔ)言的編譯程序gcc這個(gè)程序來(lái)編譯,就可以制作一個(gè)可執(zhí)行的二進(jìn)制程序。
事實(shí)上,在編譯過程中還會(huì)生成目標(biāo)文件(以*.o擴(kuò)展名形式存在)。此外,有時(shí)候,我們會(huì)在程序當(dāng)中調(diào)用其他的外部子程序,或者是利用其他軟件提供的函數(shù)功能,這個(gè)時(shí)候,我們就必須在編譯的過程當(dāng)中將該函數(shù)庫(kù)加進(jìn)去。如此一來(lái),編譯程序就可以將所有的程序代碼與函數(shù)庫(kù)做一個(gè)鏈接以生成正確的可執(zhí)行文件。
2. 使用傳統(tǒng)程序語(yǔ)言進(jìn)行編譯
- 單源碼文件制作可執(zhí)行文件:
// 比如我們用C編寫一個(gè)hello.c的源代碼,期望輸出Hello World!
vim hello.c
// 我們可以用gcc編譯,可執(zhí)行文件的文件名默認(rèn)是a
gcc hello.c
// 執(zhí)行
./a.out
- 多源碼文件利用目標(biāo)文件制作可執(zhí)行文件:
由于源碼文件有時(shí)候并非只有一個(gè),所以我們無(wú)法直接進(jìn)行編譯。這個(gè)時(shí)候就需要先生成目標(biāo)文件,然后再以鏈接制作成為二進(jìn)制可執(zhí)行文件。
// 通過-c參數(shù)編譯目標(biāo)文件。-O參數(shù)為生成優(yōu)化
gcc [-O] -c thanks_1.c thanks_2.c
// 此時(shí)目錄里多了thanks_1.o和thanks_2.o兩個(gè)目標(biāo)文件
// 進(jìn)行鏈接成為可執(zhí)行文件,通過-o參數(shù)指定生成的可執(zhí)行文件名。-Wall參數(shù)可產(chǎn)生更多的編譯過程信息
gcc [-Wall] -o thanks thanks_1.o thanks_2.o
// 然后就可以執(zhí)行了
./thanks
-
加入外部函數(shù)庫(kù)
// 若上面的代碼使用到了三角函數(shù)sin,那么在生成可執(zhí)行文件時(shí),要鏈入函數(shù)庫(kù)
gcc [-Wall] -o thanks thanks_1.o thanks_2.o -lm [-L/lib -L/usr/lib -I/usr/include]
// -l:是加入某個(gè)函數(shù)庫(kù)的意思
// m:則是libm.so這個(gè)函數(shù)庫(kù),其中,lib與擴(kuò)展名(.a或.so)不需要寫
// 所以-lm表示使用libm.so(或libm.a)函數(shù)庫(kù)的意思。
// -L:后面接的路徑是函數(shù)庫(kù)搜索目錄。上面是Linux默認(rèn)函數(shù)庫(kù)目錄,可以不寫
// -I:后面接的路徑是源碼內(nèi)的include文件的所在目錄。上面是Linux默認(rèn)include目錄,可以不寫
### 3. 用make進(jìn)行宏編譯
* 為什么要用make
假設(shè)有4個(gè)源碼文件,分別是main.c、haha.c、sin_value.c和cos_value.c。按照上面的方式,我們得這么做:
// 1. 先進(jìn)行編譯目標(biāo)文件,最終會(huì)有4個(gè).o的文件出現(xiàn)
gcc -c main.c
gcc -c haha.c
gcc -c sin_value.c
gcc -c cos_value.c
// 2. 再鏈接成為可執(zhí)行文件,并加入libm數(shù)學(xué)函數(shù),以生成main可執(zhí)行文件
gcc -o main main.o haha.o sin_value.o cos_value.o -lm -L/usr/liba -L/lib
// 3. 運(yùn)行文件
./main
> 一套軟件通常有一堆程序代碼文件,使用gcc來(lái)編譯的過程并不簡(jiǎn)單??梢允褂胢ake進(jìn)行編譯過程的簡(jiǎn)化。
執(zhí)行make時(shí),會(huì)在當(dāng)前目錄下搜索Makefile文件,Makefile文件記錄了源碼如何編譯的詳細(xì)信息。通常軟件開發(fā)商會(huì)在軟件包里提供configure(或config)文件,用以檢測(cè)用戶的操作系統(tǒng)環(huán)境是否滿足條件。
所以,你要進(jìn)行的任務(wù)只有兩個(gè),先執(zhí)行./configure生成Makefile,再執(zhí)行make編譯。
* 嘗試使用make
vi makefile
// 1. 先編輯makefile規(guī)則文件,內(nèi)容只要制作出main這個(gè)可執(zhí)行文件
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>鍵生成的空格
// 2. 使用makefile規(guī)則文件進(jìn)行編譯
rm -f main *.o <==現(xiàn)將之前的目標(biāo)文件移除
make
* makefile的基本語(yǔ)法與變量
目標(biāo): 目標(biāo)文件1 目標(biāo)文件2...
<tab> gcc -o 預(yù)新建的可執(zhí)行文件 目標(biāo)文件1 目標(biāo)文件2
以剛才上一個(gè)范例進(jìn)一步說明,我們也可以有兩個(gè)以上的操作:
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 hah.o sin_value.o cos_value.o
如此一來(lái),makefile就具有兩個(gè)目標(biāo),如果想要清除,輸入make clean,如果想要建立main,輸入make main。如果想要先清除再生成main,則輸入make clean main
* 用變量簡(jiǎn)化makefile
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}
* Tarball軟件安裝的步驟
1. ./configure --prefix=/usr/local/apache
這個(gè)步驟就是建立makefile文件。這個(gè)步驟的相關(guān)信息應(yīng)該要參考一下同目錄下的README或INSTALL文件。configure比較重要的參數(shù)是--prefix,表示軟件最終安裝的目錄,如果沒有指定,默認(rèn)為/usr/local??梢灾挥?/configure --help查看有哪些參數(shù)。
2. make clean
清理目標(biāo)文件。因?yàn)檎l(shuí)也不知道源碼里是否包含上次編譯過的目標(biāo)文件(*.o)存在。
3. make
make會(huì)依據(jù)makefile當(dāng)中的默認(rèn)工作進(jìn)行編譯的行為。主要是進(jìn)行g(shù)cc來(lái)將源碼編譯成可執(zhí)行文件,通常還需要一些函數(shù)庫(kù)的鏈接??蓤?zhí)行文件放置在當(dāng)前目錄下。
4. make install
最后的安裝步驟,依據(jù)makefile里關(guān)于install的選項(xiàng),將數(shù)據(jù)安裝到默認(rèn)的目錄中,就完成了。
* Tarball軟件安裝建議
通常建議把軟件安裝在/usr/local/software下,源碼則放在/usr/local/src下。
例如,我們將apache安裝在/usr/local/apache當(dāng)中,那么你的目錄會(huì)變成:
/usr/local/apache/etc
/usr/local/apache/bin
/usr/local/apache/lib
/usr/local/apache/man
為避免每次使用絕對(duì)路徑執(zhí)行的麻煩,可以將/usr/local/apache/bin加入PATH里。
另外/usr/local/apache/man也需要加入man page搜索路徑中去。
/etc/man.config內(nèi)的40~50行左右寫入如下一行:
MANPATH/usr/local/apache/man
### 4. 增加函數(shù)庫(kù)的讀取性能
> 函數(shù)庫(kù)分為靜態(tài)和動(dòng)態(tài)函數(shù)庫(kù),靜態(tài)函數(shù)庫(kù)在編譯的時(shí)候直接整合到執(zhí)行程序中,所以最終文件會(huì)比較大些,若函數(shù)庫(kù)升級(jí),整個(gè)可執(zhí)行文件必須重新編譯才能整合新版函數(shù)庫(kù)。
動(dòng)態(tài)函數(shù)庫(kù),沒有別整合到可執(zhí)行文件里,當(dāng)可執(zhí)行文件使用到函數(shù)庫(kù)時(shí),程序才會(huì)去讀取函數(shù)庫(kù)使用。Linux大多是將函數(shù)庫(kù)做成動(dòng)態(tài)函數(shù)庫(kù)。
* 增加函數(shù)庫(kù)讀取性能
比如mysql的函數(shù)庫(kù)在/usr/lib/mysql位置,我可以這么做:
vi /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/lib/mysql <==這一行新增的
// 將/etc/ld.so.conf的數(shù)據(jù)讀入緩存當(dāng)中,同時(shí)也將數(shù)據(jù)記錄一份在/etc/ld.so.cache文件中
idconfig
// 列出目前所有函數(shù)庫(kù)數(shù)據(jù)內(nèi)容(/etc/ld.so.cache內(nèi)的數(shù)據(jù))
ldconfig -p
* 解析程序依賴的動(dòng)態(tài)函數(shù)庫(kù)
// -v選項(xiàng),增加顯示其他版本信息
ldd [-v] /usr/bin/passwd
### 5. 校驗(yàn)軟件正確性
軟件下載站,一般提供了軟件的md5或sha1指紋碼,可以用以下方式校驗(yàn)是否被修改過:
* 對(duì)比指紋
// 將結(jié)果與網(wǎng)站的指紋碼比對(duì),一致則未被他人修改
md5sum CentOS-5.3-i386-netinstall.iso sha1sum CentOS-5.3-i386-netinstall.iso
我們可以利用這個(gè)機(jī)制,為L(zhǎng)inux系統(tǒng)上一些重要的文件創(chuàng)建指紋數(shù)據(jù)庫(kù),比如下面這些文件:
/etc/passwd
/etc/shadow(假如你不讓用戶改密碼了)
/etc/group
/usr/bin/passwd
/sbin/portmap
/bin/login(這個(gè)也很容易被黑客利用)
/bin/ls
/bin/ps
/usr/bin/top
使用md5sum檢查一次,將指紋記錄下來(lái),然后經(jīng)常以shell script方式由程序自行檢查指紋是否一致。