最近工作中遇到個問題,就是多個系統跑著不同版本的內核,不同架構的ARM芯片,上層的業務程序能否二進制歸一(共鏡像)。
根據自己對Linux的了解,glibc是否可以在ABI層面做到向前兼容。那個整個系統能否做到呢?這勾起了我的分析和思考。
試想一下,一個程序從源代碼到最終的二進制,有哪些組件參與了編譯和鏈接過程,大概如下:
需要分析各組通能否做到二進制兼容性,以及是如何做到的。下面我對各組件,以思維導圖來分析是否能滿足ABI兼容性。
上面的思維導圖把我想到的組件都進行細分,把每個細節都覆蓋到。當然,還會有一些細節是我沒有想到的。下面對不那麼常見的組件進行說明:
從分析來看,大部分軟件都是可以保持向前兼容的。這就是為什麼從一台機制上的程序拷貝到另一台機制上,程序還能正常運行。
噢,這到底是巧合呢?還是什麼:所有Linux 程序都是在所有機器上運行。我也帶個著這個問題去找一些資料。
想信大家聽說到POSIX規范,Linux Standard Base(LSB)規范。起初,我以為LSB是API規范而非ABI規范。當我去深入分析時,發現它是一個ABI規范,它解決兩方面的問題:
最近Linux基金會發起LSB項目就是希望Linux發行商能做到相互兼容,並且也能向前兼容。解決Linux應用的可移植性和兼容性。
LSB實際是是一組ABI接口的定義,它規范了運行環境所需要的類型,宏,變量和函數的二進制接口。
那麼,哪些東西受到LSB的制約呢?也即LSB規范約束的范圍多廣。剛開始,我還以為只有kernel, glibc等一些關鍵的組件。事實上,打開LSB官網說明會發現它包羅萬象,從命令,ELF,glibc接口,到桌面,腳本語言等等都有相關的規定。
毫無疑問,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 於上海 燦鴻台風來襲