當前,雖然Linux還不很普及,在Linux下編寫和編譯程序的人不多。但是我相信,隨著Linux性能的不斷提升和逐漸普及,會有許多自由軟件出現,也會有許多人成為Linux下的程序員。我結合自己的經驗,介紹一下Linux下編寫和編譯程序所要注意的幾個問題,奉獻給希望為Linux的發展作出貢獻的人們。 Linux下怎樣編譯程序? 大多數Linux程序都是由C語言編寫的並由GNU C編譯而成。現在GCC是各種發行套件的一部分。有關最新GCC編譯器的版本、文章和補丁請看FTP://ftp.gnu.org/pub/gnu/。 由C++編寫的程序必須由GNU C++編譯,GNU C++也是各種發行套件的一部分,在以上網址也有最新版本和補丁。 編譯2.0.x的內核需要2.7.2.x版本的GCC,如用象GCC 2.8.x, EGCS, or PGCC別的編譯器編譯內核可能產生不可預想的後果。 怎樣移植其它Unix程序到Linux上? 總得來說,Unix上的程序不需要做改動,只要簡單的按照提示就可以移植到Linux上,如果安裝過程中出現錯誤信息,而你又不知道怎麼處理,你可以猜或略去,不過這樣產生的程序往往帶有bug。所以最好還是問一下有經驗的人。 如果要從BSD-ish移植程序,試一試在編譯時加上-I/usr/include/bsd 和 ?lbsd命令。 什麼是ld.so,從哪可以找到它? ld.so是動態函數庫裝載器。過去,使用共享函數庫的程序在原代碼開頭使用約3K的空間來尋找和加載共享函數庫,現在,這段代碼被加進了一個特殊共享函數庫/lib/ld.so,所有的程序都可以使用該共享庫,這樣就節省了磁盤空間,而且升級方便。 ld.so可以從以下網址得到tsx-11.mit.edu/pub/linux/packages/GCC/。 怎樣升級庫函數而不使系統崩潰? 注意:進行此操作應該養成做備份的習慣,因為這項操作很容易出錯。 如果你升級象libc4這樣的老函數庫,這個過程會變得非常困難。而且你應該在該系統上讓libc4和libc5共存,因為,有些老程序還需要它。升級libc5也一樣。 升級動態庫的問題常出現在當你移走老的函數庫時,用來升級的程序也運行不了了。有許多方法可以解決這個問題。一個方法就是暫時備份一下運行程序所需函數庫,它們一般在/lib/、/usr/lib/、 /usr/local/lib/、或其它的地方,在文件/etc/ld.so.conf中都有詳細記錄。 例如,當你升級libc5時,目錄/lib/中有如下文件 libc.so.5 libc.so.5.4.33 libm.so.5 libm.so.5.0.9 這些是C函數庫和數學庫,拷貝它們到文件/etc/ld.so.conf中含有的其它的目錄,如/usr/lib/中: cp -df /lib/libc.so.5* /usr/lib/ cp -df /lib/libm.so.5* /usr/lib/ ldconfig 一定要記住運行ldconfig來升級函數庫的配置文件。 文件libc.so.5 和 libm.so.5是實際庫文件的鏈接文件,當你升級的時候,如果老的鏈接文件存在,新的鏈接不會產生,除非你使用CP命令的-f選項。CP的-d選項只復制鏈接文件,不復制原文件。 如果你需要直接覆蓋鏈接,使用ln命令的選項-f。 例如,拷貝新的庫函數覆蓋舊的。先對新的函數庫做一個鏈接,然後把函數庫和鏈接一起拷貝到/lib/中,命令如下: ln -sf ./libm.so.5.0.48 libm.so.5 ln -sf ./libc.so.5.0.48 libc.so.5 cp -df libm.so.5* /lib cp -df libc.so.5* /lib 重申一下,拷貝完別忘記運行ldconfig. 如果一切工作順利的話,你可以刪除老的函數庫的備份。 我能否把在486上編譯的代碼或編譯器拿到386上用? 當然,除非你編譯的是內核。 GCC用來在486上編譯的選項-m486 只是優化了所編譯程序,使其運行快一些。這些編譯的程序仍能很好的在386上運行,只是效果差一些。 然而,從內核1.3.35以後,采用486或Pentium選項編譯的內核不能用於386的機器。 GCC可以針對386和486進行配置。兩者區別在於,針對386配置的GCC把-m386作為缺省選項,而針對486配置的GCC把-m486作為缺省選項,僅此而已。 gcc -O6可以干什麼? 目前,它和 -O2 (GCC 2.5) 或 -O3 (GCC 2.6, 2.7)功能一樣,所有版本大於它的功能也一樣。新版內核的Makefiles使用-O2,所以你也應該用-O2。 linux/*.h 和asm/*.h在什麼地方? 目錄 /usr/include/linux/ 和 /usr/include/asm/低下的文件是內核頭文件的軟鏈接,內核頭文件其實在目錄/usr/src/kernel*/低下。 怎樣作一個共享函數庫? 對ELF, 命令如下: gcc -fPIC -c *.c gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o 對a.out,從 http://tsx-11.mit.edu/pub/linux/packages/GCC/src/ 下載n.nn.tar.gz,其中包含詳細說明。建議你將共享庫由a.out升級為ELF。 為什麼我編譯的可執行程序非常大? 用ELF編譯器,生成可執行程序太大最可能的原因是沒有合適的.so庫與你使用的庫函數鏈接。對每一個象libc.so.5.2.18的函數庫,應該有一個象libc.so的鏈接。 用a.out編譯器,生成可執行程序太大可能是使用了-g選項,這會生成靜態鏈接庫而不是動態鏈接庫。 從哪可以得到對於Linux的‘lint’? 大部分‘lint’的功能已經內置進了GCC,打開GCC的-Wall選項會打開許多有用的外部警告。 還有一個叫`lclint'的軟件功能和傳統的lint差不多,原代碼可以在http://larch.lcs.mit.edu/ /pub/Larch/lclint/中找到。