歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

內核對比:麒麟操作系統有否抄襲?

   一、引言    麒麟操作系統是由國防科技大學、中軟公司、聯想公司、浪潮公司和民族恆星公司五家單位合作研制的服務器操作系統。按照麒麟官方的說法:    “Kylin服務器操作系統是國家863計劃的重大研究成果,擁有完全自主版權的內核,與Linux在應用上二進制兼容,並支持64位,是中國獨立研發成功的、具有完全自主知識產權的服務器操作系統。”

 

[1] —— 來自麒麟官方網站 http://www.kylin.org.cn/news.htm和 863計劃官方網站[2] http://www.863.org.cn/863_105/indust/indust_news/200409160008.Html

    “銀河麒麟操作系統是針對未來的主流網絡服務和高性能計算服務的需求,參照國際主流標准,參考Darwin、 FreeBSD、Linux和其它商用操作系統,借鑒UNIX操作系統和微內核操作系統的設計思想,設計並實現具有自主版權的、可支持多種CPU芯片和多種計算機體系結構的、具有高性能、高可用性與高安全性的、並與Linux應用和設備驅動二進制兼容的中文服務器操作系統,” ——摘自麒麟操作系統2.0.21內自帶的幫助文檔    近日,有不少人對麒麟操作系統宣稱的“完全自主版權”和“中國獨立研發成功”這兩個核心問題產生了質疑。隨著麒麟2.0.14和2.0.21系統可以通過麒麟的官方網站下載後( http://www.kylin.org.cn/download.htm ),這種質疑的聲音越來越大。麒麟除內核以外的應用大部分都來自自由組織GNU的代碼,這些代碼並不屬於“中國獨立研發”,而且他們的版權也不屬於麒麟操作系統的開發者。更有甚者,有人開始通過反匯編麒麟操作系統內核發現和美國的FreeBSD開放源代碼操作系統非常相似。隨後又有人成功的用 FreeBSD的內核啟動了麒麟操作系統。按照麒麟官方的介紹,麒麟具有Linux的二進制兼容的能力,可是絲毫沒有提及與FreeBSD的兼容性,使得麒麟內核與FreeBSD的關系變得比較引人注目。在官方介紹中的簡簡單單的“參考”是無法解釋這種相似程度的。    在強烈的關注聲中,麒麟開發人員在2006年2月16日,給出了一個說明,《關於銀河麒麟操作系統的說明》[3],發布在 http://www.kylin.org.cn/download.htm .其中提到了和FreeBSD的關系:    “課題組通過評測和分析,認為當時正在研發中的FreeBSD 5.0 具有比Unix SVR4.2 更好的發展勢頭,特別是SMPng 項目的開展,為FreeBSD 5.0 支持SMP 對稱多處理器系統奠定了良好的基礎,因此銀河麒麟操作系統的系統服務層從SVR4.2 升級到當時正在研發中的FreeBSD 5.0.”    聲明發出後一定程度上得到了大家諒解,可是雖然提及和FreeBSD的關系,卻又十分隱晦,既沒有明確的對官方網站新聞中的報道失實承認錯誤,沒有明確闡述麒麟的操作系統是否具有“完全知識產權”以及是否是“中國獨立研發”,甚至也沒有對官方頁面上的事實報道進行修正。而且,既然說明使用了FreeBSD 5.0的代碼,卻又說僅限於系統服務層,而絲毫未提及所占比例。這依舊讓人們對這個獲得863計劃軟件重大專項的資助的操作系統到底有多少創新產生一個大大的疑問。    為了調查清楚麒麟操作系統內核自主創新的百分比,以及與其它操作系統之間的關系,我將麒麟操作系統內核與FreeBSD、NetBSD、OpenBSD、 Linux和Solaris的內核進行了可執行代碼的相似度分析。    在整個過程中,我將盡量保持客觀的原則進行分析。由於麒麟操作系統屬於封閉源代碼系統,因此在無法獲得內核源代碼的情況下,我將只進行二進制可執行代碼文件的相似度分析。由於可執行代碼受編譯環境、內存分布情況以及模塊的變動的影響很大,因此,會產生即使采用同一套代碼,卻產生很低的相似度情況。但是,對操作系統內核這種大型軟件系統來說,卻不會因為不同的代碼而產生很高的相似度的情況。因此,我們將這次對二進制可執行代碼分析所得的相似度作為相似度的下限。換句話說,真實的相似度應該會高於此次分析結果,但是由於分析方法的局限性,無法取得上限。    二、可執行文件的相似度比較    二進制可執行文件的相似度分析一直是一個難題。大家都知道,即使是同一份源代碼,使用同一個編譯器,可用不同的編譯參數進行編譯後,代碼也會產生極大的差異。當發生有人因為盜用別人的源代碼而產生的侵權後,如果不能夠將二者的源代碼拿出進行比較的話,判斷是否抄襲非常困難。因此,一直以來或多或少,總會有人無所顧忌的將開放源代碼的軟件拿來加入到自己的軟件中,或者干脆就是在那些源代碼的基礎上稍加修改和更換了版權信息就宣稱是自己研發的。因為他們知道,只要不把自己的源代碼公諸於眾,那麼抄襲就很難判定。下面我就詳細說一下我采用的分析方法。    2.1 ELF可執行文件相似度分析方法    這次分析起始,我就碰到了一些難題。如果對二進制可執行文件進行基於字節的相似性分析,即使匹配上某些字節,也很難說明兩段代碼的相似性,另外匹配也很容易受到各種噪音的干擾而產生很低的相似度,可是噪音卻無法被去除。因此,使最小比較單元具有明確的語義和合理的過濾噪音是我首先要解決的問題。    2.1.1 反匯編    二進制文件的比較難以確定最小單元語義的根本問題在於二進制文件是以字節為單位,然而每個字節卻沒有特定的含義。你很難說89 e5和83 EC 89中的89相同說明什麼,在這個例子中,前者的89 e5是i386的一條指令,而後者的89則是一個立即數,所以他們相同實際上什麼都不說明。針對這次分析,由於都是可執行代碼,而且都采用了ELF的文件格式。由於這個特點,我首先將所有操作系統的內核通過objdump反匯編成匯編代碼。這樣做有一個直接的好處,就是每一行都是一條匯編語句,而每一條匯編語句又是一個程序不可分的最小邏輯單元。這樣,接下來的分析就可以基於行來進行相似性的分析,因為每出現一行相同就說明有一個最小的邏輯單元相同,如果出現連續的行相似,那麼就說明有連續的代碼段相似。相同的行越多兩個內核就越相似。並且經過反匯編後,就避免了因文件內包含的其他無關信息,如字符串、資源文件、數據文件等,對分析結果產生的影響。這個方法依舊無法避免因編譯參數差異所造成的相似度下降的影響。雖然如此,但是我很幸運,從這次分析的結果看,依舊得到了不低的相似度。    2.1.2 過濾噪音    噪音的出現有很多原因,可能是內存分布不同、代碼的增刪導致的偏移地址的變化,對相同含義的常量而數值卻不同等等。這些值的差異,可能會造成不同的執行結果,但是卻對兩段代碼的相似性比較影響不大。請看下列兩個代碼段:

c043e9e8 : c04431d8 : freebsd4_sigcode(): freebsd4_sigcode(): c043e9e8: call *0x10(%esp) c04431d8: call *0x10(%esp) c043e9ec: lea 0x14(%esp),%eax c04431dc: lea 0x14(%esp),%eax c043e9f0: push %eax c04431e0: push %eax c043e9f1: testl $0x20000,0x54(%eax) c04431e1: testl $0x20000,0x54(%eax) c043e9f8: jne c043e9fd c04431e8: jne c04431ed c043e9fa: movl 0x14(%eax),%gs c04431ea: movw 0x14(%eax),%gs c043e9fd: mov $0x158,%eax c04431ed: mov $0x158,%eax c043ea02: push %eax c04431f2: push %eax c043ea03: int $0x80 c04431f3: int $0x80 c043ea05: jmp c043ea05 c04431f5: jmp c04431f5 c043ea07: nop c04431f7: nop   左邊的代碼是來自FreeBSD 5.3內核的,而右邊的代碼來自麒麟2.0.21/18的內核。通過人的分析,我們可以得出這兩段代碼實際上是相同的。可是對於計算機程序比較的時候,就不盡然。請注意上述的有顏色的數字。用藍色表示的代碼地址[4]、綠色表示的偏移地址、紅色表示的立即數、深藍色表示的函數偏移地址和粉色表示的函數地址,這些數字的不同,就造成了代碼比較時候的失敗。上述13行代碼,如果就這樣比較的話,只有函數名一行可以匹配。因此雖然是相同的代碼,卻只有7.7%的相似度。下面我們就來去除這些干擾。    首先,我們將代碼行地址、函數跳轉地址和函數偏移地址去除。代碼行所在的地址,實際上是說明了代碼所在內存的位置,內存的位置會隨著代碼的刪改而很容易產生變動,這些對我們比較代碼邏輯沒有意義。其中有些絕對地址,我們將其替換為“{Address}”,這樣既不受地址變化的影響,又不至影響了代碼的含義。    然後我們將綠色的偏移地址替換成特定字符串“{Offset}”。產生偏移地址的原因一般有兩種,一種是結構體,另一種是數組。即使不對結構體刪改,而僅僅是對結構體的聲明順序的變動都可以造成偏移地址的不同,我們在這裡只關心程序在這裡用到了一個偏移地址,而不關心用的到底是偏移了多少。數組的用法雖然不常出現,但是即使出現其中的位置也是很容易發生變動的。因此在這裡,我們也將偏移地址的數值替換成統一的字符串。最後,我們來處理紅色的立即數。當然立即數並不是只有上述的幾種情況下出現,雖然在上述的例子中,兩邊的立即數都完全一樣,單是在某些情況下還是會出現不同。    立即數在程序中一般是常量,而常量有可能是與系統相關的數值,或者僅僅是一個符號,而不在乎具體數值。無論是什麼含義,常量雖然在執行過程中不會改變,在設計過程中卻很容易發生變動。不過對我們分析代碼邏輯沒有太大的影響,因此,在分析的時候我們對數值進行模糊化,將其替換為“{Number}”這個特定字符串。    至此,上述代碼將會變為:

: : freebsd4_sigcode(): freebsd4_sigcode(): call *{Offset}(%esp) call *{Offset}(%esp) lea {Offset}(%esp),%eax lea {Offset}(%esp),%eax push %eax push %eax testl {Number},{Offset}(%eax) testl {Number},{Offset}(%eax) jne jne movl {Offset}(%eax),%gs movw {Offset}(%eax),%gs mov {Number},%eax mov {Number},%eax push %eax push %eax int {Number} int {Number} jmp jmp nop nop   現在這兩段代碼的相似度將變成真實的100%.    2.1.3 代碼段順序調整    經過上面的噪音過濾後,代碼已經能夠在基本不影響代碼邏輯的前提下去除了噪音的影響。可是,還有一種情況會對匹配結果帶來較大的影響。就是代碼塊位置的前後變動,我們來看下面這兩段代碼的比對。  

begin(): < mov {Address},%eax < lea {Offset}(%eax),%esp < xor %ebp,%ebp < mov {Address},%esi < mov %esi,{Offset}(%eax) < pushl {Address} < call < add {Number},%esp < call < add {Number},%esp < sigcode(): sigcode(): call *{Offset}(%esp) call *{Offset}(%esp) lea {Offset}(%esp),%eax lea {Offset}(%esp),%eax push %eax push %eax testl {Number},{Offset}(%eax) testl {Number},{Offset}(%eax) jne jne movl {Offset}(%eax),%gs movw {Offset}(%eax),%gs mov {Number},%eax mov {Number},%eax push %eax push %eax int {Number} int {Number} jmp jmp nop nop > begin(): > mov {Address},%eax > lea {Offset}(%eax),%esp > xor %ebp,%ebp > mov {Address},%esi > mov %esi,{Offset}(%eax) > pushl {Address} > call > add {Number},%esp > call > add {Number},%esp   和剛才一樣。左邊來自FreeBSD 5.3的代碼,右邊來自Kylin 2.0的代碼(但是為了舉例,函數前後順序稍作調整)。在兩段代碼實際上非常相似,但是由於代碼前後的順序不同,導致只有一個代碼塊sigcode()可以匹配的上,相似度僅為47.6%。針對這類情況,我的解決辦法是將代碼塊按照標號/函數名進行排序。經過排序,上述代碼段比對將變為:

begin(): begin(): mov {Address},%eax mov {Address},%eax lea {Offset}(%eax),%esp lea {Offset}(%eax),%esp xor %ebp,%ebp xor %ebp,%ebp mov {Address},%esi mov {Address},%esi mov %esi,{Offset}(%eax) mov %esi,{Offset}(%eax) pushl {Address} pushl {Address} call call add {Number},%esp add {Number},%esp call call add {Number},%esp add {Number},%esp sigcode(): sigcode(): call *{Offset}(%esp) call *{Offset}(%esp) lea {Offset}(%esp),%eax lea {Offset}(%esp),%eax push %eax push %eax testl {Number},{Offset}(%eax) testl {Number},{Offset}(%eax) jne jne movl {Offset}(%eax),%gs movw {Offset}(%eax),%gs mov {Number},%eax mov {Number},%eax push %eax push %eax int {Number} int {Number} jmp jmp nop nop

  現在,這兩段代碼只有一行不同,相似度也就變為了95.2%.但是這種依賴於標號/函數名排序的做法有效的程度實際上是有局限的。首先,並不是所有函數名都會保存於可執行代碼中,至少inline函數就會在編譯時擴展到調用的語句位置,還有一些函數在編譯器優化時被優化掉。所以,不同的編譯器,或者不同的編譯參數都有可能導致某些函數名在執行體中消失,從而導致排序失敗。    另外,不是所有的可執行體都會保留函數名,對於Windows的PE文件來說,如果不用debug模式編譯的話,除了導出函數外,其他的函數名一般不會保存在執行文件中,在我用同樣的方法分析Windows文件內核的時候出現了比較嚴重的問題,即使血親關系很近的兩個版本的Windows內核,無論排序或者不排序,相似度都非常的低,對於這類PE文件根本無法反映出相似度。所以,在最終的分析中,我剔出了原本列在比較目標中的XP內核。因為ELF的這個特點,這次我的分析將只對使用ELF的文件格式的內核進行分析。    2.1.4 比較    在原本的計劃中,我曾考慮采用常用於字符串相似度比較的編輯距離(Levenshtein Distance)算法[5].這個算法的含義,是計算兩字符串之間的距離有多遠。編輯距離是指,從原字符串變化到目的字符串最少需要進行多少次包括添加、修改、刪除在內的操作。舉例而言:如果計算kitten和sitting之間的編輯距離,我們最少需要進行3次操作,  

1、 kitten -> sitten (修改s->k) 2、 sitten -> sittin (修改i->e) 3、 sittin -> sitting (增加 g)  因此,kitten和sitting之間的編輯距離是3.這個算法是俄國的科學家Vladimir Levenshtein在1965年提出的。這個算法主要是應用在DNA分析、拼字檢查、語音辨識和抄襲偵測上。[6] 但是這個算法的計算復雜度太高,是O(nm)的復雜度。對於平均大小在100萬行的操作系統內核源代碼來說,就是萬億次級別的比對。對於普通的計算機,平均每兩個內核的比對就要花去數小時。而此次參與比對的內核將有20個左右,完成一個比較完整的比對過程將會出現幾百次比對,那麼就要花數個月的時間,不太現實。因此,這次我采用的是簡化的比對辦法。通過diff命令來比較兩個內核源文件的差異。Diff使用的是一種更聰明的計算方法,雖然最壞情況差不太多,但是大多數情況下具有較高的性能[7].    通過diff給出的結果可以得知第一個文件增改多少行代碼後,就可以變為第二個文件。diff的算法和其實對於修改我們並不介意,我們只關心增加多少行代碼就可以變為第二個文件。假設內核A的代碼有a行,內核B的代碼有b行。而從內核A變化到內核B需要添加c行,由內核B變化到內核A需要d行。由此,我們可以得知,在內核A中,存在有b-c行代碼和內核B是相同的。因此,我們將內核A中所存在的內核B的代碼行數除以內核A自身的代碼行數定義為兩個內核的相似度,即

A->B的相似度 = (b-c) / a  由公式可知,A->B和B->A的計算結果將有可能不同。因為我們判斷相似度的原因不單純是看二者的差異,更重要的是看他們之間的血親關系的遠近,因此我們取雙向轉換中的最大值,作為A<->B之間的相似度。

A-B間的相似度 = max( (b-c) / a, (a-d) / b )

  2.1.5 小結    分析方法還有待完善,可以看出,二進制可執行文件的分析依舊還有很大的難度,很容易受到各種外圍環境的變化而導致相似度大幅下降,而無法反映真實的相似度。因此對於那些刻意隱瞞相關性的二進制可執行文件來說還是比較容易的逃過這種分析方法的檢測。但是,分析方法的缺陷卻只會導致相似度的下降,而不會導致差異很大的代碼產生很高的相似度。因此,我這次采用這次分析方法主要就是確定麒麟操作系統內核與其他操作系統之間的相似度的下限,並從數據中試圖分析出他們的血親關系。    2.2 多種操作系統內核相似度比較    為了比對盡量客觀,這次參加比對的操作系統內核包括,FreeBSD, NetBSD, OpenBSD, Linux, Solaris和銀河麒麟操作系統,共6個操作系統,22個內核。原計劃中,要將Mac OS X中的Darwin 8.0.1, 7.0.1拿來比對,可是由於其文件格式是Mach-O的,而我又沒有支持Mach-O的objdump,所以暫時無法參與比對。另外,原計劃曾打算拿相關性更差的Windows NT系列的系統內核來進行比對,可是由於之前所說的PE格式問題而導致的相似度沒有參考價值,所以,這次也沒有將其列入最終的比對。為了確認比對的有效性,我們將先對FreeBSD, NetBSD和OpenBSD之間的比對來審視其比對效果。    2.2.1 FreeBSD間不同版本內核相似度分析    FreeBSD是一種Unix衍生操作系統,由BSD, 386BSD和4.4BSD發展而來的Unix的一個重要分支。而BSD的全稱是“伯克利軟件發布”,是美國伯克利大學計算機系統研究組所制作的一套包括內核在內完整的操作系統,起源於AT&T的Unix V6,但是後來由於與AT&T的版權糾紛問題,徹底的刪除了AT&T在BSD內核中的代碼,大約占10%左右。也正是這場官司,而給了 Linux得以飛速發展的機遇。在版權問題解決後,BSD借助其高質量的代碼,在開放源代碼的世界裡有了飛速的發展,分別產生了3個重要的分支, FreeBSD, OpenBSD, NetBSD.FreeBSD發展至今,已經成為公認的相當可靠和健壯的操作系統。[9,10]    因為焦點集中在FreeBSD身上,而且特別是5.x和6.x的系統上,因此這回參與比較的FreeBSD的內核版本較多,分別有FreeBSD 5.0, 5.1, 5.2, 5.2.1, 5.3, 5.4, 5.5 beta 4和6.0.    

點擊查看大圖

  上表中所列出的是FreeBSD的各個版本之間的差異行數,即前面所說到的c。左邊列出的是原始內核,頂端列出的是目的內核。左邊給出了原始內核的行數。差異行數和相似度具有相同的含義,畢竟相似度也是通過差異行數計算出來的,因此在以後的敘述中,我們將只列出相似度對比的表格。下面就是FreeBSD各個版本之間的內核相似度比較。

點擊查看大圖

  由於操作系統是逐步發展而來的,因此從5.0-5.5 beta 4都是在前者的基礎上,修補前者中出現的bug,並增添新的特性而產生的。我們可以從這個FreeBSD的相似度表中看到這種傳承關系。我們可以看出,基本上是越靠近當前版本相似度越高,而離當前版本越遠相似度就越低。其中有一些特例的情況,5.1和5.2似乎比較特殊,可能是由於某種原因在5.1中策略有所調整,而在5.2.1或者5.3中又逐漸的恢復回來。    5.2.1和5.2的相似度達到了99.80%,這是正常的,由於在5.2之後,有一系列關鍵服務,如wu-FTP, OpenSSH和XFree86等的緩沖區溢出的漏洞被揭露出來,致使FreeBSD出於安全考慮而在5.2發布後僅一個月多的時間就立即發布了新的版本,因此5.2.1和5.2的內核上的差異實際上很低,主要是在外圍程序上修補了很多安全漏洞[15].但是出乎我意料的,我沒想到在很容易被干擾而降低相似度的情況下,竟然可以達到這麼高的相似度,說明這種分析方法對於代碼相似度分析在一般情況下是有效的。究其原因,應該是因為 FreeBSD的前後傳承關系,所以不同的版本雖然代碼有不少變動,但是默認的內核配置文件變動不大,因此才有可能出現這種比較高的相似度。另外我們也可以看出,FreeBSD在5.3以後,包括5.4和5.5的內核變動量都不大,由此可以感覺到5.x的系統可能已經基本成熟。    FreeBSD 6.0與5.3以前版本的相似度都不太高,主要是因為6.0已經是和5.x屬於不同的代碼分支,相對於5.x來說代碼有了較大的變化。而另一方面,6.0 的分支是在5.4版本發布後建立的,因此,6.0的內核與之前內核的相似度偏低,卻和FreeBSD 5.3, 5.4, 5.5 beta 4的相似度較高。總體上,基本符合版本相近,代碼相近的客觀事實,分析方法是成功的。    2.2.2 FreeBSD、NetBSD和OpenBSD的內核相似度分析    NetBSD和FreeBSD一樣,也是從美國加州伯克利大學的4.3BSD和386BSD衍生出來的Unix操作系統。它以設計簡潔、代碼規范和高可移植性的特點而著稱。從服務器到嵌入式設備都有它的身影[10].而OpenBSD則是從NetBSD 1.0衍生而來的[11].因此OpenBSD和NetBSD相對FreeBSD而言具有更近的血親關系。  

點擊查看大圖

  從這個數據表中,我們可以看出計算出來的數據可以反映這種已知的血親關系。FreeBSD 與NetBSD和OpenBSD的相似度基本在16.5%左右,而NetBSD與OpenBSD的相似度則相對較高。NetBSD 2.1和OpenBSD的相似度為20.65% ~ 20.77%,NetBSD 3.0和OpenBSD的相似度也有18.44%,都高於FreeBSD與NetBSD和OpenBSD的相似度。雖然數值差別並不大,但是具有規律性,基本上也是客觀地反映了真實的情況的。    2.2.3 Kylin與FreeBSD, OpenBSD, NetBSD, Linux, Solaris的內核相似度分析    現在我們開始對銀河麒麟操作系統進行相似度比對。參與比對的開放源代碼操作系統內核有FreeBSD 5.0, FreeBSD 5.2, FreeBSD 6.0, NetBSD 2.1, NetBSD 3.0, OpenBSD 3.7, OpenBSD 3.8, Linux 2.6.16, OpenSolaris 5.11,共9個內核。除了剛才介紹過的FreeBSD, NetBSD和OpenBSD外,還增加了Linux和Solaris.Linux是Linus基本上從零起步寫出來的操作系統,雖然參考了Minix和 Unix的實現,但是基本上沒有大量的使用任何其它Unix發布的代碼[12].因此,雖然Linux也是一個類Unix系統,然而由於是獨立開發的,所以它和前面所列出的BSD衍生操作系統和後面將要提到的Solaris的血親關系比較遠。    從歷史的角度來講,Solaris和BSD很有淵源。在80年代,Sun基於BSD Unix發布了自己版本的UNIX,SunOS.而在90年代初,由於受到AT&T與BSD的官司影響,Sun將其SunOS 4替換為與AT&T共同開發的UNIX System V Release 4的一個版本,並更名為Solaris 2[13].在2004年早期,Sun開始了一項計劃,名為OpenSolaris,將Solaris逐步的放到開放源代碼社區中。並在2005年的6月中旬開放了大部分的Solaris源代碼[14].現在已經有一些基於OpenSolaris源代碼的操作系統,這次采用的就是一個名為Belenix的Live CD發布版本0.4.2種的內核,uname顯示的是SunOS 5.11.此次引入Solaris來進行比對,也是從一方面希望能夠從分析數據中客觀地反映出Solaris,相比Linux而言,和BSD有更近的血親關系。    關於參與比對的麒麟操作系統內核,我們將從發布版本中獲得的四個版本的內核拿來進行比對,Kylin 2.0.0, Kylin 2.0.14, Kylin 2.0.21, Kylin 2.0.21 lsb.需要說明的是,官方網站上發布了2.0.14和2.0.18.其中Kylin 2.0.0是來自於麒麟系統安裝盤的引導部分,通過uname –a顯示出的版本是2.0.0.Kylin 2.0.21雖然是官方網站給出的光盤鏡像的版本號,可是啟動後,通過uname –a得到的版本號卻是2.0.18,這點可能是麒麟開發組在版本管理上的混亂所導致的。    下面就是分析後得到的數據表;  

點擊查看大圖

  從數據表中反映出來的血親關系來看,Kylin 2.0的內核和FreeBSD 5.x的血親關系最近,在30.43%-48.18%之間,和FreeBSD 6.0的關系稍遠,在14.55%-24.61%之間。而和其他的操作系統關系都比較疏遠。和NetBSD、OpenBSD的相似度在10%左右,而同 Linux的相似度只有5.38%,與OpenSolaris的相似度雖然比NetBSD和OpenBSD還高,達到了12.50%,但是這個絕對數值不應該視為OpenSolaris與麒麟的關系更接近。因為,OpenSolaris的代碼行數僅有396,534行,僅相當於NetBSD的1/4.在相似度計算公式中,分母較小,容易致使結果的相似度較大,因此不應該說麒麟內核和Solaris更相似,應該說麒麟內核同Solaris,NetBSD和OpenBSD的相似度相當。    另外,我們可以注意到OpenSolaris和FreeBSD 6, NetBSD, OpenBSD的相似度略高於其他系統內核,但是都比較低。我們從這個不大的差異中可以感覺到Solaris同BSD的或近或遠的關系。其實雖然 Solaris代碼已經不是基於BSD構建的Unix了,但是由於SVR4中也吸收了BSD的部分代碼,因此Solaris在相似度上,還是客觀的體現了和BSD偏近的關系。從數據中我們還可以看到麒麟的這幾個內核的相似度很高。Kylin 2.0.0和Kylin 2.0.21 lsb的相似度是100%,Kylin 2.0.14和2.0.21的相似度也是接近100.00%.其中的具體差異行數如下:  

點擊查看大圖

  我們可以看出其實光盤引導用的內核同安裝後的/boot/kernel_lsb/ 目錄下的內核是相同的。而Kylin 2.0.21和2.0.14相比僅僅修改了幾十行代碼而已,變動很小,從數值上看,變動主要是增加了一些代碼。而從2.0.0到2.0.14變動稍大一些。    在後面的分析中,我們沒必要對很相似的內核一起進行重復分析,因此,將基於Kylin 2.0.0和Kylin 2.0.21這兩個麒麟內核進行分析。從現在的結果我們已經可以看出麒麟和FreeBSD的5.x版本有很近的血親關系,最高達到了與FreeBSD 5.2的48.18%的相似度,這種相似性甚至已經明顯超過了和FreeBSD具有很近的同源關系的NetBSD, OpenBSD.即使是最初基於NetBSD的代碼而建立的OpenBSD,在與其淵源極深的NetBSD比較時,最高也不過20.77%的相似度。    至此,我們基本上可以確定麒麟操作系統內核中有大量的FreeBSD 5.x 的源代碼。為了進一步確定麒麟操作系統和FreeBSD的相似性到底有多少,我們接下來將針對Kylin內核和FreeBSD的內核作比較。    2.2.4 Kylin與FreeBSD各個版本間的內核相似度分析    這次我們針對Kylin和FreeBSD這兩個操作系統的內核進行相似度的比對。參與比對的將包括Kylin的2個典型內核和FreeBSD 5.x全系列內核,具體是Kylin 2.0.0, Kylin 2.0.21, FreeBSD 5.0, FreeBSD 5.1, FreeBSD 5.2, FreeBSD 5.2.1, FreeBSD 5.3, FreeBSD 5.4, FreeBSD 5.5 beta4.    

點擊查看大圖

  Kylin 2.0.0和FreeBSD 5.3的相似度達到了60.26%,與FreeBSD也達到了59.04%的相似度。我們可以注意到,即使是FreeBSD的5.0 – 5.3版本之間的相似度也沒有超過40.04%.5.3、5.4和5.5的高相似度前面已經解釋了,應該是5.x系列的內核趨於穩定了,因此修補較多增添新的特性較少所致。按照麒麟開發人員的解釋,麒麟操作系統內核服務層使用的是FreeBSD 5.0的代碼。可是,從我們的分析數據可以明顯看出,Kylin 2.0.0和FreeBSD 5.0的相似度有40.53%,而與FreeBSD 5.3的相似度達到了60.26%,因此我們有理由相信麒麟使用的是FreeBSD 5.3或者5.4的代碼。    當然,我們可以理解為這是開發人員的聲明[3]中的一個筆誤,他想說FreeBSD 5.x,而不是FreeBSD 5.0.但是,另一方面,如果說僅僅是外圍服務層使用的是FreeBSD的話,那麼麒麟與FreeBSD 5.3的相似度不應該高過FreeBSD自家不同版本之間的相似度。既然麒麟2.0.0內核與FreeBSD 5.3達到了60.26%的相似度,那麼我們可以肯定地說,麒麟操作系統內核源代碼至少有一半以上使用的是FreeBSD 5.3的源代碼。    2.2.5 Kylin與FreeBSD 5.3, 5.4不同編譯配置下的內核相似度分析    為了能夠進一步了解麒麟操作系統內核同FreeBSD內核的相似度,接下來,我們將對FreeBSD 5.3和5.4在不變動任何源代碼的情況下,重新進行編譯,增加一些在Kylin 2.0中出現的模塊。這樣做的是希望在不修改FreeBSD代碼的前提下,看看不同的編譯配置是否能夠使得FreeBSD與麒麟操作系統內核的相似度更高。    這次,我們在FreeBSD的內核編譯配置文件GENERIC中增加如下三個選項:  

options COMPAT_LINUX options LINPROCFS device sound

  因為麒麟內核的一個亮點就是可以做到和Linux的二進制兼容,所以這主要是增加FreeBSD的Linux兼容性。其實事實上FreeBSD已經可以很好的兼容Linux二進制代碼了,按照FreeBSD的內核設計,它完全可以同時支持多種ABI(應用程序二進制接口),並支持同時運行不同系統可執行文件。通過加載COMPAT_LINUX模塊,FreeBSD就已經做到了和Linux可執行文件間的二進制兼容,可以執行大部分Linux程序[17].    而LINPROCFS模塊則是模擬了Linux的進程文件系統,也就是我們在Linux下見到的/proc目錄,很多Linux的程序需要用到這個系統,因此加載這個模塊後,可以讓Linux更好的在FreeBSD上運行[18].    最後增加了sound設備,因為我們通過分析,發現Kylin內核裡面加載了各種聲卡驅動。需要提及的是,麒麟系統啟動比較慢,有可能也是因為編譯了過多的不必要的模塊進內核所導致的。    

點擊查看大圖

  通過比對,我們可以看到,隨著增加了Linux兼容性和聲卡驅動模塊後,Kylin 2.0與FreeBSD的5.3、5.4的相似度均有小幅提高。其中Kylin 2.0.0內核和FreeBSD 5.3的相似度為61.19%.我們有理由相信,隨著更多合適的內核模塊的加入,Kylin 2.0和FreeBSD的內核相似度有可能會進一步提高。    實際上,經過內核模塊的比對,我們也發現了Kylin內核中出現了很多疑似是FreeBSD的其他模塊,但是由於每次編譯和比對要花費大量的時間,因此,我沒有能夠一一的加以測試。如果有興趣的朋友可以進一步測試麒麟系統內核與不同的內核配置文件之間的相似度。    2.2.6 同一份FreeBSD 5.3代碼,不同編譯配置下的內核相似度分析    接下來,我們將在不修改任何FreeBSD 5.3內核源代碼的前提下,嘗試用不同的內核編譯配置文件對FreeBSD 5.3內核進行編譯。希望能夠通過這樣的嘗試看出,同一份源代碼,在不同配置文件下能夠產生最低多低的相似度,換句話說,就是使相似度下降多少百分比。在測試中,由於編譯和比對的時間太慢,所以,我只用3個不同的內核配置文件編譯內核,這相對於可能出現的內核數量是一個很小的比例。因此,我不能夠得出最低使相似度下降的百分比,但是我能夠得出至少可以使相似度下降多少百分比。換句話說,我能夠測試出一個相似度可能被降低的范圍,但是實際能夠降低的范圍比這個還要大。  

點擊查看大圖

  我只是很少的修改了幾個內核編譯選項,我盡量使生成的內核大小不要差異太大。最後選定了3個比較合適的內核配置文件,它們與FreeBSD 5.3默認配置的內核差異從71.62%到97.47%.我們可以看到僅僅將內核配置文件稍加改動,就可以使同一份源代碼編譯出來的內核文件降低將近 30%的相似度。可以預知的趨勢是,隨著改動的增大,將能夠降低更多的相似度。    既然在不變動源代碼的情況下,就可以將相似度降低到70%左右,那麼僅僅是服務層采用FreeBSD 5.3代碼的麒麟系統內核本應該有相當低的相似度,但是分析數據卻得到了61.19%高相似度,因此麒麟操作系統內核的自主代碼的比例確實是一個比較值得關注的問題。    2.3 結論    經過這次分析,我們比較了麒麟操作系統內核同FreeBSD, NetBSD, OpenBSD, Linux和Solaris內核的相似度。在發現麒麟內核與FreeBSD 5.x有30.43%-48.18%的相似度後,將麒麟內核與FreeBSD 5.x各個版本進行了比對。通過比對看到麒麟系統與FreeBSD 5.3默認內核達到了60.26%的相似度,在經過微小調整內核配置文件後,相似度又得到了進一步的提高,達到了61.19%.在繼續調整內核配置文件之後,這個相似度還有進一步提升的空間。隨後,我們在不修改FreeBSD 5.3源代碼的情況下,僅僅通過配置文件的變動,就使內核相似度降低到了71.62%,而且還有可能降的更低。    經過分析,我們可以看出麒麟操作系統與FreeBSD 5.3具有血親關系,而且麒麟系統相對於FreeBSD 5.3的改動,還沒有FreeBSD 5.3相對於FreeBSD 5.2.1改動大。從61.19%的相似度,我們可以認定,麒麟操作系統中至少有60%的代碼是來自於FreeBSD 5.3的源代碼。由於簡單的修改配置文件就可以使相同代碼相似度降低到71.62%,而我們最終所得到的61.19%又是僅僅是麒麟內核同FreeBSD 5.3內核相似度的最小值,因此,實際的麒麟操作系統與FreeBSD 5.3在源代碼上的相似度很有可能會達到甚至超過90%.    我們可以推測(但不確定)麒麟操作系統內核可能是通過以下幾個步驟產生的。首先是在FreeBSD 5.3內核源代碼的基礎上進行了部分的修改,可能是為了增強與LSB的兼容性。然後,開發了Keta內核模塊,來實現Kernel-based靜態頁面web加速器。最後,以FreeBSD的默認內核配置文件GENERIC為基礎,編譯了更多的可選模塊進內核。這麼做的目的可能是為了讓內核更具有通用性。如果確實如此,那麼生成的麒麟操作系統內核與其說是一個新的操作系統內核,不如說是被麒麟開發者打了內核補丁的FreeBSD 5.3更為恰當。    三、尾聲    我們很難推測麒麟在內核創新的百分比,從已知的數據我們只能說,創新可能只有10%到20%之間。首先,麒麟的官方說明中提到“主要是由具有Mach 風格的基本內核層、具有BSD 風格的系統服務層和具有Windows 界面風格的桌面環境組成,前兩層在核態運行。”采用Mach微內核層+FreeBSD內核服務層的做法是其一個亮點。微內核構架加上一個成熟操作系統的服務層,是目前比較流行的一個做法,Mac OS X就是這樣。在對Mac OS X的xnu內核源代碼分析過程中,就可以看到其中的兩層內核結構,很清晰。不過在我們反匯編麒麟操作系統內核的分析過程中,竟然連一個與Mach相關的內核函數都沒有看到,許多關鍵的模塊也基本上和FreeBSD相同而看不到Mach的身影,因此我們對於麒麟操作系統內核是否真如官方說明所宣稱的那樣, “具有Mach 風格的基本內核層”,還是抱有很大疑問的。    其次,從其對外宣稱的一些麒麟的特性上看,絕大多數都是FreeBSD已經成熟的特性。比如,對Linux達到二進制兼容,事實上,FreeBSD很早以前就已經做到了和Linux二進制兼容了,麒麟直接采用了FreeBSD的內核源代碼,也自然而然的支持了這個特性,無非是在於LSB兼容上進一步的做了一些工作。麒麟系統的所宣稱的安全性應該也是繼承於FreeBSD長期積累下來的健壯和穩定性上。至於內核級的Web服務器Keta,確實是來自國防科技大學的原創,可以從http://openketa.sourceforge.net/ 取得源代碼。不過恰恰是這個內核級的Web服務器Keta,降低了麒麟所宣稱的安全性,而且也暴露了國防科技大學在安全性上認知的不足。    內核級代碼確實可以大幅提高性能,Linux在2.4的時候也曾經采用一個叫做TUX的內核級的Web加速器來進行靜態頁面的加速處理。不過這個一直是爭論的焦點,相當多的安全人士不推薦Linux這樣設計,因為內核級代碼雖然較快,但是,一旦發生溢出等安全攻擊,那麼攻擊者就可以直接將自己的代碼注入內核空間執行,具有系統最高權限,而不受約束。這將給系統安全性帶來極大的隱患。另外,內核級的Web加速器也有其自身弱點,由於功能受限,而不能夠用動態頁面,只能夠支持靜態頁面,所有的動態頁面只有轉交給另一個真實的Web服務器,比如Apache Web Server,才能夠處理。所以對於動態頁面,內核的Web加速器並沒有什麼明顯效果。隨著Linux 2.6的NPTL引入,用戶模式下的多任務性能得到了大幅提高,TUX就很快被移出標准內核了。而FreeBSD的多任務模型和Linux很不同,特別是在FreeBSD 5.x後多任務模型有很大的改進,FreeBSD的用戶模式的多任務性能並不是很差,為了這個不大的性能提高,而嚴重的降低系統安全性,實在是一個不明智的舉動。在這種情況下,還宣稱自己是高安全性,顯得很不倫不類。    而且,從編譯進麒麟內核的模塊看,我們可以感到很多桌面系統的模塊被加到了默認內核中,但是對外卻宣稱是服務器操作系統。我們都知道,安全的原則是最小化服務原則。多一個服務,多一個驅動,就多引入了一份不穩定和不安全。可是麒麟內核卻加載了很多類似於屏幕保護模塊、聲卡模塊、顯卡圖形驅動模塊、ACPI 電源管理的內核模塊,這些模塊對於一個服務器來說,並不是必須的,而且其中很多代碼會給系統帶來很大的安全隱患。這絕不單單是引導速度變慢的問題,麒麟宣稱自己是服務器操作系統,但是在這點的選擇上也是很不明智的。    

  最後需要提及的是,麒麟所安裝的軟件大部分是GNU的開放源代碼軟件,這些軟件遵循GPL.它要求如果對任何代碼進行了修改,必須開放修改過的源代碼。但不幸的是,麒麟操作系統雖然修改了部分的代碼,卻沒有開放出修改後的源代碼。從這種意義上說,麒麟操作系統對這些GNU的開源軟件有侵權嫌疑。    附錄A 進一步分析    如果想進一步的分析麒麟與其他操作系統的相似性,也可以從objdump導出的函數名稱的相似度來比較。我曾經分析過FreeBSD 5.3內核和麒麟內核objdump出的函數名的差異。FreeBSD 5.3有14101個函數,Kylin 2.0有14399個函數,其中有4個函數出現在了FreeBSD 5.3而沒有出現在Kylin 2.0中;有302個函數出現在了Kylin 2.0 objdump的文件裡,而沒有出現在FreeBSD 5.3的objdump文件裡。經過分析,這302個函數中有223都可以在FreeBSD 5.3的源代碼裡找到,沒有被objdump出來有可能是因為編譯環境不同。還剩下79個函數可能是麒麟新增的函數,他們是:    

+ acd_describe_proc(): + ad_print_proc(): + ata_info(): + ata_proc_print(): + bus_usb_proc(): + g_conftxt_class_proc(): + g_conftxt_geom_proc(): + g_conftxt_proc(): + ifa_ifwithnet_packet(): + kevent_epoll_ctl(): + kevent_epoll_wait(): + kqueue_scan_epoll(): + linprocfs_doata0info(): + linprocfs_doata1info(): + linprocfs_donetarp(): + linprocfs_donetroute(): + linprocfs_dopartitions(): + linprocfs_doprogress(): + linprocfs_doscsi(): + linprocfs_dousbdevices(): + linprocfs_dousbhub(): + linux_emul_convpath_orig(): + linux_gifindex(): + linux_ioctl_floppy(): + linux_sifflags(): + linux_to_bsd_sifhwaddr(): + mdchange_vnode(): + mpt_get_tgt_negotiated_params(): + mpt_physdisk_status(): + mpt_print_header(): [OpenBSD] + mpt_print_raid_config(): + mpt_raid_vol_status(): + mpt_read_cfg_page_with_alloc(): + mpt_read_config_info_raid(): [OpenBSD] + mpt_set_tgt_params(): + packet_abort(): + packet_appenctl(): + packet_attach(): + packet_bind(): + packet_connect(): + packet_control(): + packet_detach(): + packet_dhd_input(): + packet_disconnect(): + packet_init(): + packet_input(): + packet_output(): + packet_peeraddr(): + packet_proto_input(): + packet_send(): + packet_shutdown(): + packet_sockaddr(): + ptmsclose(): + ptmsopen(): + ptmx_clone(): + ptmxclose(): + ptmxinit(): + ptmxopen(): + raid_get_physdisk_by_num(): + read_raid_info(): + resolve_raid_targets(): + scsi_proc_inquiry(): + shmperm(): + splash_progress(): + syscons_progress(): + sysctl_kern_umass(): + usb_bus_exist(): + usbd_add_procinfo(): + usbd_devinfo_sn(): + usbd_remove_procinfo(): + xpt_announce_proc(): + xpt_find_umass(): + xpt_proc_periph(): + xptdaannouncefunc(): 以及 + vfs_nmount(): + mpt_read_config_info_ioc(): + linux_epoll_create(): + linux_epoll_ctl(): + linux_epoll_wait():

  如果單從函數名比對的統計上看的話,14399個函數,只有79個函數可能是原創的。與FreeBSD 5.3在函數名上的相似度有99.45%。這個相似程度十分驚人,但是僅憑函數名相似不足以說明邏輯上相似,因此,在分析報告中,這個分析數據只作為參考數據放到附錄中。感興趣的朋友可以進一步的分析。  附錄B 參考資料

1. 麒麟官方網站 http://www.kylin.org.cn/ 2. 863計劃官方網站 http://www.863.org.cn/ 3. 《關於銀河麒麟操作系統的說明》 http://www.kylin.org.cn/download.htm 4. GNU Assembler手冊 http://sourceware.org/binutils/docs-2.16/as/index.html 5. Levenshtein Distance, in Three Flavors, by Michael Gilleland http://www.merriampark.com/ld.htm 6. 維基百科全書: Levenshtein Distance http://en.wikipedia.org/wiki/Levenshtein_distance 7. An Algorithm for Differential File Comparison, by J. W. Hunt, M. D. Mcllroy http://www.cs.dartmouth.edu/~doug/diff.ps 8. 基於改進編輯距離的中文相似句子檢索 車萬翔、劉挺、秦兵和李生 http://ir.hit.edu.cn/ 9. A Brief History of FreeBSD http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/history.html 10. 維基百科全書:NetBSD http://en.wikipedia.org/wiki/NetBSD 11. 維基百科全書:OpenBSD http://en.wikipedia.org/wiki/Openbsd 12. Linus Torvalds biography http://www.linux.org/lininfo/linus.html 13. A Brief History of Solaris (PDF)http://unixed.com/Resources/history_of_solaris.pdf 14. Overview of OpenSolaris http://www.opensolaris.org/os/about/ 15. FreeBSD 5.2.1 Release Notes http://www.freebsd.org/releases/5.2.1R/relnotes-i386.html#SECURITY 16. 維基百科全書:UNIX System V http://en.wikipedia.org/wiki/SVR4 17. FreeBSD Handbook, Chapter 10 Linux Binary Compatibility http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/linuxemu-advanced.html 18. Man page of PROCFS(5) http://www.freebsd.org/cgi/man.cgi?query=procfs&sektion=5&manpath=FreeBSD+5.4-RELEASE




Copyright © Linux教程網 All Rights Reserved