歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 談談Linux應用程序 ABI兼容性

談談Linux應用程序 ABI兼容性

日期:2017/2/28 14:00:21   编辑:Linux教程

背景

最近工作中遇到個問題,就是多個系統跑著不同版本的內核,不同架構的ARM芯片,上層的業務程序能否二進制歸一(共鏡像)。

根據自己對Linux的了解,glibc是否可以在ABI層面做到向前兼容。那個整個系統能否做到呢?這勾起了我的分析和思考。

ABI兼容依賴什麼

試想一下,一個程序從源代碼到最終的二進制,有哪些組件參與了編譯和鏈接過程,大概如下:

  • 內核導出用戶態頭文件
  • gcc編譯器,gcc提供的靜態.o/.a,以及它提供的動態庫(如libgcc_s.so)
  • glibc
  • 第三方開源庫

需要分析各組通能否做到二進制兼容性,以及是如何做到的。下面我對各組件,以思維導圖來分析是否能滿足ABI兼容性。

上面的思維導圖把我想到的組件都進行細分,把每個細節都覆蓋到。當然,還會有一些細節是我沒有想到的。下面對不那麼常見的組件進行說明:

  • 內核導出頭文件: 構建過交叉編譯工具鏈是嵌入式裡面常做的事情,工具鏈的構建需要使用內核導出的導文件。這是內核態和用戶約定好的基礎類型和數據結構,比如我們常見的time_t,pid_t等等類型。整於用戶態軟件都以它為基石。
  • glibc版本機制:glibc對大部分符號都打上版本號,日後在高版本的glibc中,由於POSIX/LSB標准的變化,或者函數接口有變,它會創建該符號的另一新版本,但原來版本的符號仍然存在,同時語義和參數保持不變。它通過這種機制來保證ABI的向前兼容性(請注意,無法保證向後的兼容性)

從分析來看,大部分軟件都是可以保持向前兼容的。這就是為什麼從一台機制上的程序拷貝到另一台機制上,程序還能正常運行。

Linux standard Base(LSB)

噢,這到底是巧合呢?還是什麼:所有Linux 程序都是在所有機器上運行。我也帶個著這個問題去找一些資料。
想信大家聽說到POSIX規范,Linux Standard Base(LSB)規范。起初,我以為LSB是API規范而非ABI規范。當我去深入分析時,發現它是一個ABI規范,它解決兩方面的問題:

  • 在發行版Linux A上運行的程序,可以運行在發行版本Linux B上。
  • 應用程序在現在的機器上運行,也能在未來新系統和機器上運行。

最近Linux基金會發起LSB項目就是希望Linux發行商能做到相互兼容,並且也能向前兼容。解決Linux應用的可移植性和兼容性。

LSB實際是是一組ABI接口的定義,它規范了運行環境所需要的類型,宏,變量和函數的二進制接口。

那麼,哪些東西受到LSB的制約呢?也即LSB規范約束的范圍多廣。剛開始,我還以為只有kernel, glibc等一些關鍵的組件。事實上,打開LSB官網說明會發現它包羅萬象,從命令,ELF,glibc接口,到桌面,腳本語言等等都有相關的規定。

誰應該遵守LSB規范

毫無疑問,kernel, glibc等都應該遵守LSB標准。事情上,並非如此。 LSB希望Linux發布版(如RedHat, SUSE, Ubuntu)能遵守LSB,因此它提供了LSB的測試套和LSB的認證服務。

那麼Kernel和glibc就真的不需要考慮LSB了吧,答案是否定的。整個kernel/glibc和各大Linux知名組件都以開源方式進行開發,它裡面的技術早已不是什麼密秘了,各大公司都有工程師參與,所有公司都希望這些軟件都是遵守LSB,使所有軟件都能輕易地融合在一起,不希望讓發生行商花很大力氣去集成。因此所有軟件都是會盡量遵守LSB規范,但無法排除有那麼一兩個例外的Case。

glibc是大家用得最多的組件,也算是我比較了解的組件之一,到網上找了一些它的兼容性分析,發現它也不能保證100%向前兼容。不能完全兼容的發生在2.16.0和2.13兩個版本上。當前對於一般的軟件,這個兼容性是完全足夠了的。

“向後”兼容性

那麼Linux能做到向後兼容性嗎?答案是否定的,因為LSB也無法做到向後兼容。

那問題來了,如果我需要做到向後兼容呢?假如有下面這種場景:

很多服務器都是Ubuntu 7.04,算是8年前的服務器了,數量很多。同時也會有服務器使用了12.04,數量較少。但12.04上的編譯器較新,支持很多安全功能。架構師的訴求就是:能否基於12.04版本運行環境做開發編譯,生成的服務程序能同時運行在7.04和12.04兩個服務器上。

我能想到的解決辦法:

  • 找到Ubuntu 7.04和12.04兩服務器運行軟件,所遵守的LSB版本,服務程序只能調用這兩LSB完全兼容的接口
  • 在編程和鏈接服務程序時,可以指定程序使用的LSB標准(Ubuntu 7.04版本的LSB)。

對於第一個方法,個人認為可行,但約束很多。方法二未知可行,後續再分析

這就是“向後”兼容性想討論的一個問題。它不是真正的向後兼容性,完全是依賴於向前兼容來實現的。

後記

兼容性,完全不是我熟悉的東西,只是工作上遇到問題,做了初步分析。希望通過blog記錄我的思考,當某一天,我對這個知識有深入的經驗,再跟大家分享。如有寫得不正確,或者誤導的內容,請指正,謝謝!

2015/7/11 於上海 燦鴻台風來襲

Copyright © Linux教程網 All Rights Reserved