麒麟操作系统内核,同其他操作系统内核的相似性分析
Copyright (c) 2006 Dancefire (dancefire#gmail).
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.
作者:Dancefire (dancefire # gmail dot com) 2006/04/27
一、引言
麒麟操作系统是由国防科技大学、中软公司、联想公司、浪潮公司和民族恒星公司五家单位合作研制的服务器操作系统。按照麒麟官方的说法:
“Kylin 服务器操作系统是国家 863 计划的重大研究成果,拥有完全自主版权的内核,与 Linux 在应用上二进制兼容,并支持 64 位,是中国独立研发成功的、具有完全自主知识产权的服务器操作系统。”[1]
“银河麒麟操作系统是针对未来的主流网络服务和高性能计算服务的需求,参照国际主流标准,参考 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 的关系变得比较引人注目。在官方介绍中的简简单单的“参考” 是无法解释这种相似程度的。
“课题组通过评测和分析,认为当时正在研发中的 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
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 <freebsd4_sigcode+**0x15**> | c04431e8: jne c04431ed <freebsd4_sigcode+**0x15**>
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 <freebsd4_sigcode+**0x1d**> | c04431f5: jmp c04431f5 <freebsd4_sigcode+**0x1d**>
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 <freebsd4_sigcode+{Offset}> | jne <freebsd4_sigcode+{Offset}>
movl {Offset}(%eax),%gs | movw {Offset}(%eax),%gs
mov {Number},%eax | mov {Number},%eax
push %eax | push %eax
int {Number} | int {Number}
jmp <freebsd4_sigcode+{Offset}> | jmp <freebsd4_sigcode+{Offset}>
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 <sigcode+{Offset}> jne <sigcode+{Offset}>
movl {Offset}(%eax),%gs | movw {Offset}(%eax),%gs
mov {Number},%eax mov {Number},%eax
push %eax push %eax
int {Number} int {Number}
jmp <sigcode+{Offset}> jmp <sigcode+{Offset}>
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
add {Number},%esp add {Number},%esp
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 <sigcode+{Offset}> jne <sigcode+{Offset}>
movl {Offset}(%eax),%gs | movw {Offset}(%eax),%gs
mov {Number},%eax mov {Number},%eax
push %eax push %eax
int {Number} int {Number}
jmp <sigcode+{Offset}> jmp <sigcode+{Offset}>
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->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_5.0 | freebsd_5.1 | freebsd_5.2 | freebsd_5.2.1 | freebsd_5.3 | freebsd_5.4 | freebsd_5.5.b4 | freebsd_6.0 |
freebsd_5.0 | 913,353 | – | 697423 | 712361 | 714811 | 969174 | 1001579 | 1016967 | 1146371 |
freebsd_5.1 | 958,699 | 652223 | – | 682433 | 681769 | 1029692 | 1002484 | 1034263 | 1112613 |
freebsd_5.2 | 1,048,418 | 572280 | 604662 | – | 3252 | 817759 | 865407 | 850969 | 1124929 |
freebsd_5.2.1 | 1,049,592 | 493098 | 607199 | 2078 | – | 816434 | 870479 | 881654 | 1124304 |
freebsd_5.3 | 1,161,593 | 742327 | 762747 | 705826 | 724190 | – | 35581 | 78219 | 977778 |
freebsd_5.4 | 1,174,287 | 744511 | 811979 | 732332 | 733290 | 22906 | – | 25985 | 901307 |
freebsd_5.5.b4 | 1,187,447 | 741616 | 783626 | 735617 | 734211 | 40295 | 12975 | – | 358820 |
freebsd_6.0 | 1,271,723 | 791490 | 805184 | 905427 | 907359 | 753022 | 766311 | 622653 | – |
上表中所列出的是 FreeBSD 的各个版本之间的差异行数,即前面所说到的 c。左边列出的是原始内核,顶端列出的是目的内核。左边给出了原始内核的行数。
差异行数和相似度具有相同的含义,毕竟相似度也是通过差异行数计算出来的,因此在以后的叙述中,我们将只列出相似度对比的表格。
下面就是 FreeBSD 各个版本之间的内核相似度比较。
原始内核 \ 目的内核 | 汇编行数 | freebsd_5.0 | freebsd_5.1 | freebsd_5.2 | freebsd_5.2.1 | freebsd_5.3 | freebsd_5.4 | freebsd_5.5.b4 | freebsd_6.0 |
freebsd_5.0 | 913,353 | – | 28.61% | 36.79% | 36.65% | 21.07% | 18.91% | 18.67% | 13.72% |
freebsd_5.1 | 958,699 | 27.24% | – | 38.18% | 38.37% | 13.76% | 17.92% | 15.98% | 16.60% |
freebsd_5.2 | 1,048,418 | 32.53% | 33.77% | – | 99.80% | 32.80% | 29.46% | 32.09% | 14.00% |
freebsd_5.2.1 | 1,049,592 | 40.04% | 33.49% | 99.69% | – | 32.89% | 28.95% | 29.13% | 14.05% |
freebsd_5.3 | 1,161,593 | 14.72% | 16.87% | 29.49% | 28.01% | – | 98.03% | 95.49% | 25.31% |
freebsd_5.4 | 1,174,287 | 14.38% | 12.49% | 26.92% | 26.94% | 96.97% | – | 98.91% | 31.54% |
freebsd_5.5.b4 | 1,187,447 | 14.46% | 14.74% | 26.34% | 26.56% | 94.43% | 97.80% | – | 76.88% |
freebsd_6.0 | 1,271,723 | 9.58% | 12.07% | 11.24% | 11.18% | 32.13% | 32.08% | 44.41% | – |
由于操作系统是逐步发展而来的,因此从 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_5.3 | freebsd_6.0 | netbsd_2.1 | netbsd_3.0 | openbsd_3.7 | openbsd_3.8 |
freebsd_5.3 | 1,161,593 | – | 25.31% | 16.55% | 16.61% | 16.78% | 16.74% |
freebsd_6.0 | 1,271,723 | 32.13% | – | 16.65% | 16.22% | 15.89% | 16.24% |
netbsd_2.1 | 1,503,585 | 13.08% | 13.68% | – | 53.35% | 17.53% | 16.72% |
netbsd_3.0 | 1,616,659 | 11.76% | 12.65% | 24.40% | – | 13.96% | 14.61% |
openbsd_3.7 | 1,228,137 | 15.60% | 16.54% | 20.77% | 18.44% | – | 88.89% |
openbsd_3.8 | 1,260,707 | 15.26% | 16.52% | 20.65% | 18.47% | 84.56% | – |
从这个数据表中,我们可以看出计算出来的数据可以反映这种已知的血亲关系。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,这点可能是麒麟开发组在版本管理上的混乱所导致的。
下面就是分析后得到的数据表;
原始内核 \ 目标内核 | 汇编行数 | fb 5.0 | fb 5.2 | fb 6.0 | k 2-0 | k 2-14 | k 2-21 | k 2-21 lsb | l 2.6.16 | nb 2.1 | nb 3.0 | ob 3.7 | ob 3.8 | os 5.11 |
freebsd_5.0 | 913,353 | – | 36.79% | 13.72% | 40.53% | 30.43% | 30.43% | 40.53% | 6.46% | 11.24% | 11.37% | 10.91% | 10.87% | 5.02% |
freebsd_5.2 | 1,048,418 | 32.53% | – | 14.00% | 48.18% | 34.02% | 34.02% | 48.18% | 5.75% | 11.02% | 10.91% | 10.95% | 10.94% | 4.55% |
freebsd_6.0 | 1,271,723 | 9.58% | 11.24% | – | 12.63% | 13.19% | 13.14% | 12.63% | 6.61% | 16.65% | 16.22% | 15.89% | 16.24% | 5.21% |
kylin_2.0.0 | 1,120,079 | 31.92% | 41.94% | 14.55% | – | 91.06% | 91.06% | 100.00% | 5.38% | 10.83% | 10.31% | 10.20% | 10.35% | 4.35% |
kylin_2.0.14 | 1,190,443 | 23.55% | 29.98% | 24.61% | 85.60% | – | 100.00% | 85.60% | 5.04% | 10.63% | 10.64% | 10.30% | 10.44% | 4.06% |
kylin_2.0.21 | 1,190,562 | 23.52% | 29.95% | 21.04% | 85.57% | 99.99% | – | 85.57% | 5.03% | 10.72% | 10.63% | 10.29% | 10.44% | 4.06% |
kylin_2.0.21_lsb | 1,120,079 | 31.92% | 41.94% | 14.55% | 100.00% | 91.06% | 91.06% | – | 5.38% | 10.83% | 10.31% | 10.20% | 10.35% | 4.35% |
linux_2.6.16 | 666,204 | 9.47% | 9.71% | 13.13% | 5.38% | 5.38% | 5.39% | 5.38% | – | 11.89% | 12.09% | 12.21% | 12.07% | 6.30% |
netbsd_2.1 | 1,503,585 | 6.49% | 7.42% | 13.68% | 8.06% | 8.18% | 7.97% | 8.06% | 5.20% | – | 53.35% | 17.53% | 16.72% | 4.10% |
netbsd_3.0 | 1,616,659 | 6.19% | 7.11% | 12.65% | 7.54% | 7.90% | 7.89% | 7.54% | 4.98% | 24.40% | – | 13.96% | 14.61% | 3.73% |
openbsd_3.7 | 1,228,137 | 7.95% | 9.58% | 16.54% | 9.27% | 9.97% | 9.71% | 9.27% | 6.43% | 20.77% | 18.44% | – | 88.89% | 5.20% |
openbsd_3.8 | 1,260,707 | 7.72% | 8.84% | 16.52% | 8.88% | 9.53% | 9.52% | 8.88% | 6.29% | 20.65% | 18.47% | 84.56% | – | 5.00% |
OpenSolaris_5.11 | 396,534 | 11.87% | 12.00% | 16.84% | 12.50% | 12.46% | 12.46% | 12.50% | 13.37% | 15.90% | 15.82% | 16.66% | 16.49% | – |
从数据表中反映出来的血亲关系来看,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%。其中的具体差异行数如下:
原始内核 \ 目标内核 | 汇编行数 | kylin_2.0.0 | kylin_2.0.14 | kylin_2.0.21 | kylin_2.0.21_lsb |
kylin_2.0.0 | 1,120,079 | – | 170,553 | 170,641 | 0 |
kylin_2.0.14 | 1,190,443 | 101,029 | – | 145 | 101,029 |
kylin_2.0.21 | 1,190,562 | 101,328 | 26 | – | 101,328 |
kylin_2.0.21_lsb | 1,120,079 | 0 | 170,553 | 170,641 | – |
我们可以看出其实光盘引导用的内核同安装后的 / 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。
原始内核 \ 目标内核 | 汇编行数 | fb 5.0 | fb 5.1 | fb 5.2 | fb 5.2.1 | fb 5.3 | fb 5.4 | fb 5.5.b4 | kylin_2.0.0 | kylin_2.0.21 |
freebsd_5.0 | 913,353 | – | 28.61% | 36.79% | 36.65% | 21.07% | 18.91% | 18.67% | 40.53% | 30.43% |
freebsd_5.1 | 958,699 | 27.24% | – | 38.18% | 38.37% | 13.76% | 17.92% | 15.98% | 28.94% | 26.11% |
freebsd_5.2 | 1,048,418 | 32.53% | 33.77% | – | 99.80% | 32.80% | 29.46% | 32.09% | 48.18% | 34.02% |
freebsd_5.2.1 | 1,049,592 | 40.04% | 33.49% | 99.69% | – | 32.89% | 28.95% | 29.13% | 48.15% | 34.47% |
freebsd_5.3 | 1,161,593 | 14.72% | 16.87% | 29.49% | 28.01% | – | 98.03% | 95.49% | 57.94% | 50.48% |
freebsd_5.4 | 1,174,287 | 14.38% | 12.49% | 26.92% | 26.94% | 96.97% | – | 98.91% | 56.24% | 51.88% |
freebsd_5.5.b4 | 1,187,447 | 14.46% | 14.74% | 26.34% | 26.56% | 94.43% | 97.80% | – | 39.47% | 50.16% |
kylin_2.0.0 | 1,120,079 | 31.92% | 20.99% | 41.94% | 41.97% | 60.26% | 59.04% | 42.59% | – | 91.06% |
kylin_2.0.21 | 1,190,562 | 23.52% | 16.68% | 29.95% | 29.93% | 52.04% | 50.87% | 50.35% | 85.57% | – |
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 内核里面加载了各种声卡驱动。需要提及的是,麒麟系统启动比较慢,有可能也是因为编译了过多的不必要的模块进内核所导致的。
原始内核 \ 目标内核 | 汇编行数 | freebsd_5.3 | freebsd_5.3_1 | freebsd_5.4 | freebsd_5.4_1 | kylin_2.0.0 | kylin_2.0.21 |
freebsd_5.3 | 1,161,593 | – | 97.47% | 98.03% | 73.12% | 57.94% | 50.48% |
freebsd_5.3_1 | 1,198,401 | 93.78% | – | 80.82% | 98.07% | 56.49% | 56.64% |
freebsd_5.4 | 1,174,287 | 96.97% | 94.55% | – | 96.58% | 56.24% | 51.88% |
freebsd_5.4_1 | 1,210,928 | 91.68% | 97.05% | 94.56% | – | 55.66% | 55.29% |
kylin_2.0.0 | 1,120,079 | 60.26% | 61.19% | 59.04% | 60.17% | – | 91.06% |
kylin_2.0.21 | 1,190,562 | 52.04% | 57.02% | 50.87% | 54.38% | 85.57% | – |
通过比对,我们可以看到,随着增加了 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 个不同的内核配置文件编译内核,这相对于可能出现的内核数量是一个很小的比例。因此,我不能够得出最低使相似度下降的百分比,但是我能够得出至少可以使相似度下降多少百分比。换句话说,我能够测试出一个相似度可能被降低的范围,但是实际能够降低的范围比这个还要大。
原始内核 \ 目标内核 | 汇编行数 | freebsd_5.3 | freebsd_5.3_1 | freebsd_5.3_2 | freebsd_5.3_3 |
freebsd_5.3 | 1,161,593 | – | 97.47% | 72.01% | 71.62% |
freebsd_5.3_1 | 1,198,401 | 93.78% | – | 96.95% | 94.32% |
freebsd_5.3_2 | 1,256,264 | 66.54% | 45.25% | – | 98.11% |
freebsd_5.3_3 | 1,271,301 | 67.10% | 89.43% | 96.95% | – |
我只是很少的修改了几个内核编译选项,我尽量使生成的内核大小不要差异太大。最后选定了 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 个函数可能是麒麟新增的函数,他们是:
如果单从函数名比对的统计上看的话,14399 个函数,只有 79 个函数可能是原创的。与 FreeBSD 5.3 在函数名上的相似度有 99.45%。这个相似程度十分惊人,但是仅凭函数名相似不足以说明逻辑上相似,因此,在分析报告中,这个分析数据只作为参考数据放到附录中。感兴趣的朋友可以进一步的分析。