標籤:
http://blog.csdn.net/xinghun_4/article/details/7905298
應用程式二進位介面(ABI-Application Binary Interface)定義了一組在PowerPC系統軟體上編譯應用程式所需要遵循的一套規則。主要包括基礎資料型別 (Elementary Data Type),通用寄存器的使用,參數的路由規則,以及堆棧的使用等等。
ABI涵蓋了各種細節:如資料類型、大小和對齊;呼叫慣例(控制著函數的參數如何傳送以及如何接受傳回值);系統調用的編碼和一個應用如何向作業系統進行系統調用;以及在一個完整的作業系統ABI中,目標檔案的二進位格式、程式庫等等。一個完整的ABI,像Intel二進位相容標準 (iBCS)[1] ,允許支援它的作業系統上的程式不經修改在其他支援此ABI的操作體統上運行。
其他的 ABI 標準化細節包括 C++ 名稱修飾[2] ,和同一個平台上的編譯器之間的呼叫慣例[3],但是不包括跨平台的相容性。
ABI不同於應用程式介面(API),API定義了原始碼和庫之間的介面,因此同樣的代碼可以在支援這個API的任何系統中編譯,然而ABI允許編譯好的目標代碼在使用相容ABI的系統中無需改動就能運行。 在Unix風格的作業系統中,存在很多運行在同一硬體平台上互相相關但是不相容的作業系統(尤其是Intel 80386相容系統)。有一些努力嘗試標準化ABI,以減少銷售商將程式移植到其他系統時所需的工作。然而,直到現在還沒有很成功的例子,雖然Linux標準化工作群組正在為Linux做這方面的努力。
API,顧名思義,是編程的介面, 換句話說也就是你編寫“應用程式”時候調用的函數之類的東西。對於核心來說,它的“應用程式”有兩種:一種是在它之上的,使用者空間的真正的應用程式,核心 給它們提供的是系統調用這種介面,比如 read(2),write(2);另一種就是核心模組了,它們和核心處於同一層,核心給它們提供的是匯出的核心功能,比如 kmalloc(),printk()。這些介面都是你可以在編寫程式的時候直接看到的,可以直接拿來用的。
而 ABI 是另一種形式的介面,二進位介面。除非你直接使用組合語言,這種介面一般是不能直接拿來用的。比如,核心系統調用用哪些寄存器或者乾脆用堆棧來傳遞參數,傳回值又是通過哪個寄存器傳遞迴去,核心裡面定義的某個結構體的某個欄位位移是多少等等,這些都是二進位層面上的介面。這些介面是直接給編譯好的二 進位用的。換句話說,如果 ABI 保持穩定的話,你在之前版本上編譯好的二進位應用程式、核心模組,完全可以無須重新編譯直接在新版本上運行。另一種比較特殊的 ABI 是像 /proc,/sys 目錄下面匯出的檔案,它們雖然不是直接的二進位形式,但也會影響編譯出來的二進位,如果它裡面使用到它們的話,因此這些“介面”也是一種 ABI。
你平時看到的什麼 POSIX 標準啊,C99 標準啊,都是對 API 的規定。而規定 ABI 的標準就不多,而且也沒那麼強勢,Linux 上面的 ABI 標準似乎只有 Linux Foundation 提供的一些標準。
好了,從上面我 們可以看出,其實保持一個穩定的 ABI 要比保持穩定的 API 要難得多。比如,在核心中 int register_netdevice(struct net_device *dev) 這個核心功能原型基本上是不會變的,所以保持這個 API 穩定是很簡單的,但它的 ABI 就未必了,就算是這個函數定義本身沒變,即 API 沒變,而 struct net_device 的定義變了,裡面多了或者少了某一個欄位,它的 ABI 就變了,你之前編譯好的二進位模組就很可能會出錯了,必須重新編譯才行。
你可能會感到意外,上遊的 Linux 核心其實不光不保持穩定的 ABI,它就連穩定的 API 都不會保持!而且還牛逼哄哄地寫了一個文檔,叫 stable_api_nonsense.txt。這麼做的道理是,核心一直在向前推進,而且速度很快,核心開發人員們並不想因為 API 的限制而阻礙前進的腳步!畢竟我們不想成為下一個 Windows!:-)
所以,你的驅動在不同版本的核心上不經修改直接運行那幾乎是不太可能的,就算是你允許重新編譯也未必就能不經修改編譯成功。即使在同一個大版本的不同發行版上也可能不行。
那你應該怎麼辦?最好的辦法莫過於把你的驅動貢獻到社區,匯入核心原始碼樹中,這樣一旦核心的 API 有改動,改動這個 API 的人就有義務替 你修改你的驅動的代碼,你只需要 review 一下(或者這個也會有人幫你),也省去你不少時間,何樂而不為呢?另一種辦法就是基於某個提供穩定 ABI 的核心,比如紅帽的 RHEL (認為這是廣告的人請使用 CentOS,謝謝!),紅帽的企業版核心保證有穩定的 ABI,只要你沒有跨大的版本,因為我們的原始碼裡會檢測 ABI 的變化,為此我們實在付出了不少努力。
API、ABI區別