1. 什么是開放源碼补胚、編譯程序與可執(zhí)行文件
我們使用特定編程語言(如C或Java等)壹哺,編寫的純文本文件即為源碼文件倾剿。在完成源碼文件的編寫之后,再通過編譯程序?qū)⒃创a文件編譯成操作系統(tǒng)看得懂的二進(jìn)制可執(zhí)行文件熏挎。
在Linux上最標(biāo)準(zhǔn)的程序語言為C速勇,所以我們使用C語法寫完源碼(以*.c擴(kuò)展名形式存在)后,以Linux上標(biāo)準(zhǔn)C語言的編譯程序gcc這個程序來編譯坎拐,就可以制作一個可執(zhí)行的二進(jìn)制程序烦磁。
事實(shí)上,在編譯過程中還會生成目標(biāo)文件(以*.o擴(kuò)展名形式存在)廉白。此外个初,有時候,我們會在程序當(dāng)中調(diào)用其他的外部子程序猴蹂,或者是利用其他軟件提供的函數(shù)功能院溺,這個時候,我們就必須在編譯的過程當(dāng)中將該函數(shù)庫加進(jìn)去磅轻。如此一來珍逸,編譯程序就可以將所有的程序代碼與函數(shù)庫做一個鏈接以生成正確的可執(zhí)行文件逐虚。
2. 使用傳統(tǒng)程序語言進(jìn)行編譯
- 單源碼文件制作可執(zhí)行文件:
// 比如我們用C編寫一個hello.c的源代碼,期望輸出Hello World谆膳!
vim hello.c
// 我們可以用gcc編譯叭爱,可執(zhí)行文件的文件名默認(rèn)是a
gcc hello.c
// 執(zhí)行
./a.out
- 多源碼文件利用目標(biāo)文件制作可執(zhí)行文件:
由于源碼文件有時候并非只有一個,所以我們無法直接進(jìn)行編譯漱病。這個時候就需要先生成目標(biāo)文件买雾,然后再以鏈接制作成為二進(jìn)制可執(zhí)行文件。
// 通過-c參數(shù)編譯目標(biāo)文件杨帽。-O參數(shù)為生成優(yōu)化
gcc [-O] -c thanks_1.c thanks_2.c
// 此時目錄里多了thanks_1.o和thanks_2.o兩個目標(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ù)庫
// 若上面的代碼使用到了三角函數(shù)sin注盈,那么在生成可執(zhí)行文件時晃危,要鏈入函數(shù)庫
gcc [-Wall] -o thanks thanks_1.o thanks_2.o -lm [-L/lib -L/usr/lib -I/usr/include]
// -l:是加入某個函數(shù)庫的意思
// m:則是libm.so這個函數(shù)庫,其中老客,lib與擴(kuò)展名(.a或.so)不需要寫
// 所以-lm表示使用libm.so(或libm.a)函數(shù)庫的意思僚饭。
// -L:后面接的路徑是函數(shù)庫搜索目錄。上面是Linux默認(rèn)函數(shù)庫目錄胧砰,可以不寫
// -I:后面接的路徑是源碼內(nèi)的include文件的所在目錄鳍鸵。上面是Linux默認(rèn)include目錄,可以不寫
### 3. 用make進(jìn)行宏編譯
* 為什么要用make
假設(shè)有4個源碼文件尉间,分別是main.c权纤、haha.c、sin_value.c和cos_value.c乌妒。按照上面的方式,我們得這么做:
// 1. 先進(jìn)行編譯目標(biāo)文件外邓,最終會有4個.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來編譯的過程并不簡單侦啸。可以使用make進(jìn)行編譯過程的簡化丧枪。
執(zhí)行make時光涂,會在當(dāng)前目錄下搜索Makefile文件,Makefile文件記錄了源碼如何編譯的詳細(xì)信息拧烦。通常軟件開發(fā)商會在軟件包里提供configure(或config)文件忘闻,用以檢測用戶的操作系統(tǒng)環(huán)境是否滿足條件。
所以恋博,你要進(jìn)行的任務(wù)只有兩個齐佳,先執(zhí)行./configure生成Makefile私恬,再執(zhí)行make編譯。
* 嘗試使用make
vi makefile
// 1. 先編輯makefile規(guī)則文件炼吴,內(nèi)容只要制作出main這個可執(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的基本語法與變量
目標(biāo): 目標(biāo)文件1 目標(biāo)文件2...
<tab> gcc -o 預(yù)新建的可執(zhí)行文件 目標(biāo)文件1 目標(biāo)文件2
以剛才上一個范例進(jìn)一步說明本鸣,我們也可以有兩個以上的操作:
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
如此一來,makefile就具有兩個目標(biāo)硅蹦,如果想要清除荣德,輸入make clean,如果想要建立main童芹,輸入make main涮瞻。如果想要先清除再生成main,則輸入make clean main
* 用變量簡化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
這個步驟就是建立makefile文件辐脖。這個步驟的相關(guān)信息應(yīng)該要參考一下同目錄下的README或INSTALL文件饲宛。configure比較重要的參數(shù)是--prefix,表示軟件最終安裝的目錄嗜价,如果沒有指定艇抠,默認(rèn)為/usr/local【米叮可以只用./configure --help查看有哪些參數(shù)家淤。
2. make clean
清理目標(biāo)文件。因?yàn)檎l也不知道源碼里是否包含上次編譯過的目標(biāo)文件(*.o)存在瑟由。
3. make
make會依據(jù)makefile當(dāng)中的默認(rèn)工作進(jìn)行編譯的行為絮重。主要是進(jìn)行g(shù)cc來將源碼編譯成可執(zhí)行文件,通常還需要一些函數(shù)庫的鏈接歹苦∏嗌耍可執(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)中立帖,那么你的目錄會變成:
/usr/local/apache/etc
/usr/local/apache/bin
/usr/local/apache/lib
/usr/local/apache/man
為避免每次使用絕對路徑執(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ù)庫的讀取性能
> 函數(shù)庫分為靜態(tài)和動態(tài)函數(shù)庫,靜態(tài)函數(shù)庫在編譯的時候直接整合到執(zhí)行程序中,所以最終文件會比較大些宵蕉,若函數(shù)庫升級酝静,整個可執(zhí)行文件必須重新編譯才能整合新版函數(shù)庫。
動態(tài)函數(shù)庫羡玛,沒有別整合到可執(zhí)行文件里别智,當(dāng)可執(zhí)行文件使用到函數(shù)庫時,程序才會去讀取函數(shù)庫使用稼稿。Linux大多是將函數(shù)庫做成動態(tài)函數(shù)庫薄榛。
* 增加函數(shù)庫讀取性能
比如mysql的函數(shù)庫在/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ù)據(jù)記錄一份在/etc/ld.so.cache文件中
idconfig
// 列出目前所有函數(shù)庫數(shù)據(jù)內(nèi)容(/etc/ld.so.cache內(nèi)的數(shù)據(jù))
ldconfig -p
* 解析程序依賴的動態(tài)函數(shù)庫
// -v選項(xiàng)敞恋,增加顯示其他版本信息
ldd [-v] /usr/bin/passwd
### 5. 校驗(yàn)軟件正確性
軟件下載站,一般提供了軟件的md5或sha1指紋碼谋右,可以用以下方式校驗(yàn)是否被修改過:
* 對比指紋
// 將結(jié)果與網(wǎng)站的指紋碼比對硬猫,一致則未被他人修改
md5sum CentOS-5.3-i386-netinstall.iso sha1sum CentOS-5.3-i386-netinstall.iso
我們可以利用這個機(jī)制,為Linux系統(tǒng)上一些重要的文件創(chuàng)建指紋數(shù)據(jù)庫改执,比如下面這些文件:
/etc/passwd
/etc/shadow(假如你不讓用戶改密碼了)
/etc/group
/usr/bin/passwd
/sbin/portmap
/bin/login(這個也很容易被黑客利用)
/bin/ls
/bin/ps
/usr/bin/top
使用md5sum檢查一次啸蜜,將指紋記錄下來,然后經(jīng)常以shell script方式由程序自行檢查指紋是否一致辈挂。