API、ABI區別

應用程序二進制接口(ABI-Application Binary Interface)定義了一組在PowerPC系統軟件上編譯應用程序所需要遵循的一套規則。主要包括基本數據類型,通用寄存器的使用,參數的傳遞規則,以及堆棧的使用等等。

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 的變化,爲此我們實在付出了不少努力。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章