上一個(gè)帖子提到了"硬件體系"相關(guān)的話題,今天來說說和操作系統(tǒng)相關(guān)的話題。為了不繞口,以下把Linux和各種Unix統(tǒng)稱為Posix系統(tǒng)。
★文件系統(tǒng)(FileSystem以下簡稱FS)
剛開始搞跨平臺開發(fā)的新手,多半都會碰上和FS相關(guān)的問題。所以先來聊一下FS。歸納下來,開發(fā)中容易碰上的FS差異主要有如下幾個(gè):目錄分隔符的差異;大小寫敏感的差異;路徑中禁用字符的差異。
為了應(yīng)對上述差異,你要注意如下幾點(diǎn):
1、文件和目錄命名要規(guī)范
在給文件和目錄命名時(shí),盡量只使用字母和數(shù)字。不要在同一個(gè)目錄下放兩個(gè)名稱相似(名稱中只有大小寫不同,例如foo.cpp與Foo.cpp)的文件。不要使用某些OS的保留字(例如aux、con、nul、prn)作文件名或目錄名。
補(bǔ)充一下,剛才說的命名,包括了源代碼文件、二進(jìn)制文件和運(yùn)行時(shí)創(chuàng)建的其它文件。
2、#include語句要規(guī)范
當(dāng)你寫#include語句時(shí),要注意使用正斜線"/"(比較通用)而不要使用反斜線"\"(僅在Windows可用)。#include語句中的文件和目錄名要和實(shí)際名稱保持大小寫完全一致。
3、代碼中涉及FS操作,盡量使用現(xiàn)成的庫
已經(jīng)有很多成熟的、用于FS的第三方庫(比如boost::filesystem)。如果你的代碼涉及到FS的操作(比如目錄遍歷),盡量使用這些第三方庫,可以幫你省不少事情。
★文本文件的回車CR/換行LF
由于幾個(gè)知名的操作系統(tǒng)對回車/換行的處理不一致,導(dǎo)致了這個(gè)煩人的問題。目前的局面是:Windows同時(shí)使用CR和LF;Linux和大部分的Unix使用LF;蘋果的Mac系列使用CR。
對于源代碼管理,好在很多版本管理軟件(比如CVS、SVN)都會智能地處理這個(gè)問題,讓你從代碼庫取回本地的源碼能適應(yīng)本地的格式。
如果你的程序需要在運(yùn)行時(shí)處理文本文件,要留意本文方式打開和二進(jìn)制方式打開的區(qū)別。另外,如果涉及跨不同系統(tǒng)傳輸文本文件,要考慮進(jìn)行適當(dāng)?shù)奶幚怼?BR> ★文件搜索路徑(包括搜索可執(zhí)行文件和動態(tài)庫)
在Windows下,如果要執(zhí)行文件或者加載動態(tài)庫,一般會搜索當(dāng)前目錄;而Posix系統(tǒng)則不盡然。所以如果你的應(yīng)用涉及到啟動進(jìn)程或加載動態(tài)庫,就要小心這個(gè)差異。
★環(huán)境變量
對于上述提到的搜索路徑問題,有些同學(xué)想通過修改PATH和LD_LIBRARY_PATH來引入當(dāng)前路徑。假如使用這種方法,建議你只修改進(jìn)程級的環(huán)境變量,不要修改系統(tǒng)級的環(huán)境變量(修改系統(tǒng)級有可能影響到同機(jī)的其它軟件,產(chǎn)生副作用)。
★動態(tài)庫
如果你的應(yīng)用程序使用動態(tài)庫,強(qiáng)烈建議動態(tài)庫導(dǎo)出標(biāo)準(zhǔn)C風(fēng)格的函數(shù)(盡量不要導(dǎo)出類)。如果在Posix系統(tǒng)中加載動態(tài)庫,切記慎用RTLD_GLOBAL標(biāo)志位。這個(gè)標(biāo)志位會Enable全局符號表,有可能會導(dǎo)致多個(gè)動態(tài)庫之間的符號名沖突(一旦碰到這種事,會出現(xiàn)匪夷所思的運(yùn)行時(shí)錯誤,極難調(diào)試)。
★服務(wù)/看守進(jìn)程
如果你不清楚服務(wù)和看守進(jìn)程的概念,請看維基百科(這里和這里)。為了敘述方便,以下統(tǒng)稱服務(wù)。
由于C++開發(fā)的模塊大部分是后臺模塊,經(jīng)常會碰到服務(wù)的問題。編寫服務(wù)需要調(diào)用好幾個(gè)系統(tǒng)相關(guān)的API,導(dǎo)致了與操作系統(tǒng)的緊密耦合,很難用一套代碼搞定。因此比較好的辦法是抽象出一個(gè)通用的服務(wù)外殼,然后把業(yè)務(wù)邏輯代碼作為動態(tài)庫掛載到它下面。這樣的話,至少保證了業(yè)務(wù)邏輯的代碼只需要一套;服務(wù)外殼的代碼雖然需要兩套(一個(gè)用于Windows、一個(gè)用于Posix),但他們是業(yè)務(wù)無關(guān)的,可以很方便地重用。
★默認(rèn)棧大小
不同的操作系統(tǒng),棧的默認(rèn)大小差別很大,從幾十KB(據(jù)說Symbian只有12K,真摳門)到幾MB不等。因此你事先要打聽一下目標(biāo)系統(tǒng)的默認(rèn)棧大小,如果碰上像Symbian這樣摳門的,可以考慮用編譯器選項(xiàng)調(diào)大。當(dāng)然,養(yǎng)成"不在棧上定義大數(shù)組/大對象"的好習(xí)慣也很重要,否則再大的棧也會被撐爆的。
★文件系統(tǒng)(FileSystem以下簡稱FS)
剛開始搞跨平臺開發(fā)的新手,多半都會碰上和FS相關(guān)的問題。所以先來聊一下FS。歸納下來,開發(fā)中容易碰上的FS差異主要有如下幾個(gè):目錄分隔符的差異;大小寫敏感的差異;路徑中禁用字符的差異。
為了應(yīng)對上述差異,你要注意如下幾點(diǎn):
1、文件和目錄命名要規(guī)范
在給文件和目錄命名時(shí),盡量只使用字母和數(shù)字。不要在同一個(gè)目錄下放兩個(gè)名稱相似(名稱中只有大小寫不同,例如foo.cpp與Foo.cpp)的文件。不要使用某些OS的保留字(例如aux、con、nul、prn)作文件名或目錄名。
補(bǔ)充一下,剛才說的命名,包括了源代碼文件、二進(jìn)制文件和運(yùn)行時(shí)創(chuàng)建的其它文件。
2、#include語句要規(guī)范
當(dāng)你寫#include語句時(shí),要注意使用正斜線"/"(比較通用)而不要使用反斜線"\"(僅在Windows可用)。#include語句中的文件和目錄名要和實(shí)際名稱保持大小寫完全一致。
3、代碼中涉及FS操作,盡量使用現(xiàn)成的庫
已經(jīng)有很多成熟的、用于FS的第三方庫(比如boost::filesystem)。如果你的代碼涉及到FS的操作(比如目錄遍歷),盡量使用這些第三方庫,可以幫你省不少事情。
★文本文件的回車CR/換行LF
由于幾個(gè)知名的操作系統(tǒng)對回車/換行的處理不一致,導(dǎo)致了這個(gè)煩人的問題。目前的局面是:Windows同時(shí)使用CR和LF;Linux和大部分的Unix使用LF;蘋果的Mac系列使用CR。
對于源代碼管理,好在很多版本管理軟件(比如CVS、SVN)都會智能地處理這個(gè)問題,讓你從代碼庫取回本地的源碼能適應(yīng)本地的格式。
如果你的程序需要在運(yùn)行時(shí)處理文本文件,要留意本文方式打開和二進(jìn)制方式打開的區(qū)別。另外,如果涉及跨不同系統(tǒng)傳輸文本文件,要考慮進(jìn)行適當(dāng)?shù)奶幚怼?BR> ★文件搜索路徑(包括搜索可執(zhí)行文件和動態(tài)庫)
在Windows下,如果要執(zhí)行文件或者加載動態(tài)庫,一般會搜索當(dāng)前目錄;而Posix系統(tǒng)則不盡然。所以如果你的應(yīng)用涉及到啟動進(jìn)程或加載動態(tài)庫,就要小心這個(gè)差異。
★環(huán)境變量
對于上述提到的搜索路徑問題,有些同學(xué)想通過修改PATH和LD_LIBRARY_PATH來引入當(dāng)前路徑。假如使用這種方法,建議你只修改進(jìn)程級的環(huán)境變量,不要修改系統(tǒng)級的環(huán)境變量(修改系統(tǒng)級有可能影響到同機(jī)的其它軟件,產(chǎn)生副作用)。
★動態(tài)庫
如果你的應(yīng)用程序使用動態(tài)庫,強(qiáng)烈建議動態(tài)庫導(dǎo)出標(biāo)準(zhǔn)C風(fēng)格的函數(shù)(盡量不要導(dǎo)出類)。如果在Posix系統(tǒng)中加載動態(tài)庫,切記慎用RTLD_GLOBAL標(biāo)志位。這個(gè)標(biāo)志位會Enable全局符號表,有可能會導(dǎo)致多個(gè)動態(tài)庫之間的符號名沖突(一旦碰到這種事,會出現(xiàn)匪夷所思的運(yùn)行時(shí)錯誤,極難調(diào)試)。
★服務(wù)/看守進(jìn)程
如果你不清楚服務(wù)和看守進(jìn)程的概念,請看維基百科(這里和這里)。為了敘述方便,以下統(tǒng)稱服務(wù)。
由于C++開發(fā)的模塊大部分是后臺模塊,經(jīng)常會碰到服務(wù)的問題。編寫服務(wù)需要調(diào)用好幾個(gè)系統(tǒng)相關(guān)的API,導(dǎo)致了與操作系統(tǒng)的緊密耦合,很難用一套代碼搞定。因此比較好的辦法是抽象出一個(gè)通用的服務(wù)外殼,然后把業(yè)務(wù)邏輯代碼作為動態(tài)庫掛載到它下面。這樣的話,至少保證了業(yè)務(wù)邏輯的代碼只需要一套;服務(wù)外殼的代碼雖然需要兩套(一個(gè)用于Windows、一個(gè)用于Posix),但他們是業(yè)務(wù)無關(guān)的,可以很方便地重用。
★默認(rèn)棧大小
不同的操作系統(tǒng),棧的默認(rèn)大小差別很大,從幾十KB(據(jù)說Symbian只有12K,真摳門)到幾MB不等。因此你事先要打聽一下目標(biāo)系統(tǒng)的默認(rèn)棧大小,如果碰上像Symbian這樣摳門的,可以考慮用編譯器選項(xiàng)調(diào)大。當(dāng)然,養(yǎng)成"不在棧上定義大數(shù)組/大對象"的好習(xí)慣也很重要,否則再大的棧也會被撐爆的。