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