Windows 和 Linux 应用程序从上到下调用层次比较
????????剛畢業(yè)的時(shí)候,做了將近一年的Window下的程序開發(fā),主要用MFC,那是也不明白程序在操作系統(tǒng)角度從上到下的整個(gè)調(diào)用層次。遇到調(diào)用庫函數(shù),不明白,就查MSDN,每個(gè)月1500行代碼左右,那時(shí)以為這就是軟件開發(fā)了。后來跳槽的另外一家公司,工作也是Windows下的程序開發(fā),這里可以用到多線程、COM組件,還能用到設(shè)計(jì)模式,那時(shí)高興的不得了。剛開始用到多線程,就買了一本書《WIN32多線程程序設(shè)計(jì)》,邊學(xué)邊用。
?????? 創(chuàng)建線程有好幾種方法,比如: CreatThread 和 _beginthread()等,記得當(dāng)時(shí)不明白這幾種方法有何區(qū)別,就隨便拿一個(gè)用。心中有疑問:怎么創(chuàng)建一個(gè)線程這么多函數(shù)?WINAPI、CRT、MFC 到底有何關(guān)聯(lián)?最近讀《程序員的自我修養(yǎng)》一書,給了我明確的答復(fù)。參考下圖:
?
?
????????從上圖可以看到,CRT和MFC函數(shù)最終都是調(diào)用WINAPI來實(shí)現(xiàn)的。即CRT和MFC庫函數(shù)都是對(duì)WIN API的封裝。終于明白了創(chuàng)建線程函數(shù)分屬不同的層次/類庫,如下:?
??????? 1.??? WINAPI: CreateThread();
????????2.??? CRT:???????????? _beginthread();???? 和 _beginthreadex();???????
????????3.??? MFC???????????? AfxBeginThread();
?
?
?
???????? Linux下應(yīng)用程序調(diào)用層次如下圖:?
?
?上圖只是列出了CRT,當(dāng)然也存在其它很多類庫,比如Linux下QT庫,也是對(duì)系統(tǒng)調(diào)用的封裝。
?
?從Windows和linux程序調(diào)用層次圖,我們可以看到有如下區(qū)別:
Linux下可以直接進(jìn)行程序調(diào)用,而Windows下不能直接進(jìn)行系統(tǒng)調(diào)用。即Windows下的系統(tǒng)調(diào)用接口微軟并沒有開放給developer, 而是在系統(tǒng)調(diào)用上面添加了一層WINAPI。至于微軟為什么不開放系統(tǒng)調(diào)用,而添加一層WINAPI,諸位可以參考《程序員的自我修養(yǎng)》第12章的12.3.2。Windows API是以DLL導(dǎo)出函數(shù)的形式暴露給developer的,核心DLL有kernel32.dll、user32.dll和gdi32.dll. 我們可以用dumpbin /EXPORTS *.dll命令來查看每個(gè)dll的導(dǎo)出函數(shù)。
?
根據(jù)以上2個(gè)圖,來簡單談一下跨平臺(tái)編程。大家知道windows下的應(yīng)用程序.exe放到Linux下是不能運(yùn)行的,反之,Linux下同樣不能運(yùn)行Windows下的程序,就相當(dāng)于用PDF Reader 打不開 Word文檔一樣,大家知道Windows下的可執(zhí)行文件是PE文件格式,Linux可執(zhí)行文件下是ELF文件格式。
我們程序員寫的代碼,用Windows下的編譯器連接器(cl,即 VC++編譯鏈接器)編譯連接后,生成的目標(biāo)文件是PE文件格式,同樣的代碼在Linux下用編譯器gcc編譯,鏈接器ld鏈接,生成的目標(biāo)文件是ELF文件格式。同樣的代碼在不同的平臺(tái)下編譯通過的前提是代碼中的函數(shù)符號(hào)(Symbol)能夠被正確識(shí)別,這里我們不得不提及CRT,即C Runtime, Windows下是MSVCRT, Linux下是glibc (GNU C Library). C 語言運(yùn)行庫至少包含如下功能:
1.????? 程序的啟動(dòng)和退出;
2.?????? 標(biāo)準(zhǔn)函數(shù), 既是C語言標(biāo)準(zhǔn)庫;
3.?????? I/0
4.?????? 堆heap 的 封裝和實(shí)現(xiàn);
5.?????? 調(diào)試
??? 我們主要關(guān)注第2點(diǎn):標(biāo)準(zhǔn)函數(shù),即只要代碼中我們調(diào)用函數(shù)都是C語言標(biāo)準(zhǔn)庫函數(shù),這些函數(shù)代碼在Windows和Linux下是都能識(shí)別的,因?yàn)?/span>glibc和MSVCRT都在各自的平臺(tái)上實(shí)現(xiàn)了這些函數(shù),簡單的講就是: 提供給developer的函數(shù)接口遵從C標(biāo)準(zhǔn)庫,下層實(shí)現(xiàn)調(diào)用各自系統(tǒng)的系統(tǒng)調(diào)用。如果你調(diào)用MFC庫中的函數(shù),這些函數(shù)Symbol在linux下是無法識(shí)別的。所以我們?cè)趯懣缙脚_(tái)C代碼時(shí)(我們這里不討論JAVA), 一定要調(diào)用標(biāo)準(zhǔn)C庫函數(shù),這樣完成的代碼就可以在Windows和Linux下用各自的編譯器鏈接器編譯鏈接(備注:包含的頭文件不同,因?yàn)?/span>MSVCRT和glibc導(dǎo)出c庫函數(shù)頭文件不同),生成的目標(biāo)文件就可以在各自的系統(tǒng)上運(yùn)行。?
?
?
總結(jié)
以上是生活随笔為你收集整理的Windows 和 Linux 应用程序从上到下调用层次比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “绿冻杨枝折”下一句是什么
- 下一篇: c语言实现memcpy