2014-12-22 15:38:21 lionzl 阅读数 1320
  • 2020考研专业课《计算机操作系统原理》精讲视频课程

    计算机操作系统是计算机专业必修的专业基础课程,是考研的必考科目。它的特点是概念多、较抽象和涉及面广,所以无论是大学学习还是考研,很多同学都把它当做一块硬骨头,其实只要我们掌握正确的学习方法,操作系统课程还是非常容易理解和掌握的,终在考研时取得到高分。

    67214 人正在学习 去看看 任铄
麒麟操作系统内核同其他操作系统内核的相似性分析
  
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
( PDF格式及分析所用脚本程序下载连接:http://www.dancefire.org/file/kernel_similarity_analysis_1.0.zip )
 
 
一、引言
 
麒麟操作系统是由国防科技大学、中软公司、联想公司、浪潮公司和民族恒星公司五家单位合作研制的服务器操作系统。按照麒麟官方的说法:
 
“Kylin服务器操作系统是国家863计划的重大研究成果,拥有完全自主版权的内核,与Linux在应用上二进制兼容,并支持64位,是中国独立研发成功的、具有完全自主知识产权的服务器操作系统。”[1]
 --- 来自麒麟官方网站 http://www.kylin.org.cn/news.htm
 
“银河麒麟操作系统是针对未来的主流网络服务和高性能计算服务的需求,参照国际主流标准,参考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 <freebsd4_sigcode>:                        | c04431d8 <freebsd4_sigcode>:
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>:
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   <init386>                   <
        add    {Number},%esp               <
        call   <mi_startup>                <
        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   <init386>
                                           >         add    {Number},%esp
                                           >         call   <mi_startup>
                                           >         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   <init386>                           call   <init386>
        add    {Number},%esp                       add    {Number},%esp
        call   <mi_startup>                        call   <mi_startup>
        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-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_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个函数可能是麒麟新增的函数,他们是:
  
+ 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

2017-06-10 00:27:10 a271917994 阅读数 493
  • 2020考研专业课《计算机操作系统原理》精讲视频课程

    计算机操作系统是计算机专业必修的专业基础课程,是考研的必考科目。它的特点是概念多、较抽象和涉及面广,所以无论是大学学习还是考研,很多同学都把它当做一块硬骨头,其实只要我们掌握正确的学习方法,操作系统课程还是非常容易理解和掌握的,终在考研时取得到高分。

    67214 人正在学习 去看看 任铄

linux与其他操作系统文件共享方法

前言:
我将Linux文件共享的方法分为以下几类:
1)通过简单的文件夹属性设置,提供文件的访问和拷贝;
2)通过ssh(secure shell)服务;
3)通过scp(secure copy)命令;
4)搭建文件服务器。
.......

目前我所接触到的linux文件共享的方法也就是上面几种,下面大致介绍一下各类方法的操作。

1. 文件夹属性设置

其实很多人不知道,在windows/MacOS与linux之间传输文件,都可以简单的通过文件夹属性的设置达到,windows通过设置文件夹属性为共享,添加共享的权限为everyone或其他用户;MacOS在设置-共享,选择文件共享,添加共享文件夹和用户。在ubuntu中点击alt+f2出来的搜索框中输入windows或MacOS主机的\ip地址,即可看到其所有共享的文件夹。这样就能实现从其他系统向linux拷贝文件,但是如何设置将linux文件拷出呢?办法类似于windows文件共享的设置方法。在windows中查看linux文件是通过开始-运行中输入linux主机的\ip地址,MacOS中在Finder中command+k输入linux主机的\ip地址。
上述这种方法适用于所有同学使用,尤其是非码农的同学一定要学会这种操作,节约大量的文件拷进拷出的时间。

2. 通过ssh服务

windows电脑中安装一个mobaxterm或putty(pscp)。通过ssh登录,mobaxterm可以直接拖拽文件到linux目录,也可以从中拖出。putty的附带程序pscp可以很好的实现文件拷贝,pscp是个exe文件,但是需要通过命令行来执行,放到C:\WINDOWS\system32下就能直接在命令行下使用pscp命令了,一般用法:

pscp -参数 文件名 用户名@主机ip:/目标目录
pscp -r test.file root@192.168.1.12:/home/test

3. 通过scp命令

windows to linux
scp -参数 文件名 用户名@主机ip:/目标目录
scp -r test.file root@192.168.1.12:/home/test
linux to windows
scp -参数 用户名@主机ip:/文件目录 目标目录 
scp -r root@192.168.1.12:/home/test.file ./ 

4. 通过安装文件服务器

之前为了实现文件的共享,安装了samba服务器,安装起来也十分简单,详细可见我的另外一篇博客。

5. 其他方法

NAS或自己搭建的文件服务器。
家里的路由和移动硬盘组合可以当作文件服务器使用,我现在把东西都放在移动硬盘里,将移动硬盘插在路由器上,在家里的任何一台电脑上都可以访问移动硬盘里面的数据,而且速度非常快。
除了路由之外,也可以通过树莓派来作为主体,在树莓派上搭建samba,将移动硬盘挂载到树莓派上,来作为文件服务器使用。

2013-05-13 12:00:12 xie0812 阅读数 1280
  • 2020考研专业课《计算机操作系统原理》精讲视频课程

    计算机操作系统是计算机专业必修的专业基础课程,是考研的必考科目。它的特点是概念多、较抽象和涉及面广,所以无论是大学学习还是考研,很多同学都把它当做一块硬骨头,其实只要我们掌握正确的学习方法,操作系统课程还是非常容易理解和掌握的,终在考研时取得到高分。

    67214 人正在学习 去看看 任铄

linux操作系统是在Unix操作系统的基础上发展而来的,所以也继承了Unix的优点,正是由于这些优点,才有今天的简单、健壮、强大的linux操作系统

1.首先当然是它的开源性,这一点保证了,许多计算机相关专业的各个层面的高手参与,同时融进了许多优秀的思想;

2.Unix相对其他的操作系统更简单,其他操作系统实现了上千个系统调用,而且没有明确设计目标,但Unix操作系统只有几百个系统调用,而且拥有简单、明了的设计目标;

3.在Unix系统中,所有的事都以文件的形式来处理,这一特点保证了系统中的数据和设备使用的方便;

4.Unix操作系统完全是用C语言写的,这使它有惊人的可移植性,也从另外一个方面使其被应用得到了广泛的应用;

5.Unix操作系统拥有快速的进程创建方法以及独特的fork()系统调用;

6.Unix操作系统拥有简单且健壮的进程间的通信。

2018-10-22 22:46:42 qq_37162911 阅读数 3075
  • 2020考研专业课《计算机操作系统原理》精讲视频课程

    计算机操作系统是计算机专业必修的专业基础课程,是考研的必考科目。它的特点是概念多、较抽象和涉及面广,所以无论是大学学习还是考研,很多同学都把它当做一块硬骨头,其实只要我们掌握正确的学习方法,操作系统课程还是非常容易理解和掌握的,终在考研时取得到高分。

    67214 人正在学习 去看看 任铄
  1. 计算机系统由硬件子系统和软件子系统组成
  2. 硬件系统主要由中央处理器,主存储器,辅助存储器,输入/输出设备组成
  3. 操作使用者认为操作系统是一组命令的集合,程序设计人员认为操作系统是一组功能调用程序的集合,一般认为,操作系统是一种管理计算机资源 ,控制程序执行,改善人机界面和为其他软件提供支持的系统软件。
  4. 操作系统主要的设计原则:使用方便,高效工作
  5. 操作系统分为:批处理操作系统,实时操作系统,网络操作系统,分时操作系统,分布式操作系统,多机操作系统和嵌入式操作系统。其中批处理操作系统,分时操作系统,实时操作系统是最基本的操作系统。
  6. 把用户要求计算机进行处理的一个计算问题称为一个作业,批量处理作业的操作系统为批处理操作系统,实现了计算机操作的自动化。分为批处理单道系统和批处理多道系统。
  7. 每个用户感到好像自己独占一台支持自己请求服务的计算机系统称为分时操作系统。也是支持多道处理程序的系统。
  8. 分时操作系统的特点:同时性,独立性,及时性,交互性
  9. 把由分时操作系统控制的作业为前台作业。批处理操作系统控制的为后台作业
  10. 能使计算机系统接收到外部信号后及时进行处理,并且在严格的规定时间内处理结束,在给出反馈信号的操作系统为实时操作系统。
  11. 设计实时操作系统必须要考虑实时性和可靠性
  12. 把若干台地理上分散的并具有自治功能的计算机系统用通信线路连接起来构成计算机网络称为网络操作系统。
  13. 分布式计算机系统是由多台计算机组成的一种特殊的计算机网络。称为分布式操作系统。
  14. 嵌入式操作系统是指运行在嵌入式系统中对各种部件,装置等资源进行统一协调,处理和控制的系统软件。主要特点为:微型化和实时性
  15. 从资源管理的观点看,操作系统的功能分为处理器管理,存储管理,文件管理和设备管理。处理器管理主要进行处理器的分配调度,存储管理是对主存储器进行管理。

2.计算机系统结构简介

  1. 计算机系统是由硬件和软件组成的层次式结构,最内层是硬件系统,最外层是使用计算机系统的人,人与硬件系统之间是软件系统。软件系统分为:系统软件,支撑软件,应用软件。系统软件是计算机系统中与硬件结合最紧密的软件,也是必不可少的软件。
  2. 计算机系统中用来存放程序和数据的部件是存储器。包括寄存器,主存储器,高速缓冲存储器和辅助存储器。寄存器分为:通用寄存器,指令寄存器,控制寄存器。控制寄存器分为:程序状态字寄存器,存放当前程序执行时的状态。中断字寄存器,记录出现的事件。基址寄存器,设定程序执行时间可访问的主存空间的开始地址。限长寄存器,设定程序执行时可访问的主存空间的长度。
  3. 当中央处理器在管态时可执行包括特权指令在内的一切机器指令,在目态时不允许执行特权指令。
  4. 操作系统的设计目标:正确性,高效性,维护性,移植性
  5. 操作系统结构的设计方法有无序模块法,内核扩充法,层次结构法,管程设计法。
  6. 操作系统为用户提供两种接口,操作员级的接口是一种操作控制命令,程序员级的接口是系统功能调用。
  7. 不同操作系统的系统调用不完全相同,大致分为:文件操作类,资源申请类,控制类,信息维护类

3.处理器管理

  1. 把多个计算问题同时装入一个计算机系统的主存储器并行执行,称为多道程序设计,称为多道程序设计系统。应注意的问题:存储保护,程序浮动,资源的分配和调度
  2. 把一个程序在一个数据集上的一次执行称为一个进程。因此,程序是静态的文本,进程是动态的过程。进程包括程序和程序处理的对象,进程实现了程序的功能。
  3. 进程的特性:动态性:进程是程序一次执行过程,在执行过程中进程状态不断发生变化。并发行:若干进程是可同时执行的,它们轮流占用处理器交替运行。异步性:进程的执行速度取决于自身与外界原因以及能占用处理器的时间,因此以不可预知的速度向前推进。
  4. 为了标识进程,记录各个进程执行时的情况,操作系统在创建进程时为每一个进程设置了一个进程控制块。包含以下几类:标识信息,说明信息,现场信息,管理信息。
  5. UNIX由进程控制块,正文段,数据段组成。进程控制块为分进程基本控制块称为proc结构和进程扩充控制块称为user结构。把块供多个程序共享的程序称为进程的正文段。进程的数据段分为三个部分:用户栈区,用户数据区,系统工作区。
  6. UNIX进程的状态:就绪态,运行态,睡眠态,僵死态
  7. UXIX进程树,第一个进程为0号进程称为交换进程,在由0号进程创建一个1号进程称为初始化进程。1号进程在用户态运行,为用户创建一个login进程,若有多个终端调用,则由login进程创建一个shell进程。在UNIX中,0号进程和1号进程是进程簇的老祖宗,在系统运行是永不消亡。
  8. UNIX要经常在主存和磁盘中切换,称为进程的换进换出,由0号进程完成
  9. 中断分为强迫性中断和自愿性中断
  10. 中断事件的处理:保护被中断进程的现场信息,分析中断原因,处理发生的中断事件
  11. 批处理作业的调度算法:先来先服务算法,计算时间短的作业优先算法,响应比高者优先算法,优先调度算法,均衡调度算法
  12. 我们把一个进程让出处理器由另一个进程占用处理器的过程称为进程切换,进程调度算法有:先来先服务调度算法,最高优先级调度算法,时间片轮转调度算法,分级调度算法。
  13. UNIX是一个分时操作系统,采用了动态优先数调度算法。优先数越小则优先权越高。

4.存储管理

  1. 主存空间的分配算法:最先适应算法,最优适应算法,最坏适应算法。
  2. 主存空间的回收算法:归还区有下邻空闲区,归还区有上邻空闲区,归还区既有上邻区又有下邻空闲区,归还区既无上邻空闲区又无下邻空闲区。
  3. 硬件设置两个专用的寄存器:基址寄存器和限长寄存器。分别存放当前占用处理器作业所占的始址和末址。不能满足以下公式则出现地址越界。基址寄存器<=绝对地址<=限长寄存器。
  4. 把一个存储区域移动到另一个移动区域的技术为移动。移动会增加系统的开销:把操作系统所占用的系统资源和所需的处理器时间为系统开销。移动是有条件的:应先判断是否与外围设备交换信息。
  5. 页是存储器是把主存储器分成大小相等的许多分区,每个区为一个块。相对地址=页号+页内地址
  6. 块号=字号*字长+块号,字号=i/字长,位号=i mod 字长
  7. 页面调度算法:最佳页面调度算法,先进先出页面调度算法,最近最久未使用页面调度算法,最近最不经常使用页面调度算法。

5.文件管理

  1. 文件的分类:按用途分类:系统问津啊,库文件,用户文件。保护级别分类:执行文件,只读文件,读写文件。信息流向分类:输入文件,输出文件,输入/输出文件。存放时限分类:临时文件,永久文件,档案文件。设备类型分类:磁带文件,磁盘文件,卡片文件,打印文件。文件的组织结构分类:记录式文件,流式文件,存储介质分类:顺序文件,链接文件,索引文件。
  2. 文件的保密:隐藏文件目录,设置口令,使用密码

6.进程同步与进程通信

  1. 一个进程独占处理器顺序执行时有两个特性:封闭性,可再现性
2013-08-08 14:27:35 u011440741 阅读数 337
  • 2020考研专业课《计算机操作系统原理》精讲视频课程

    计算机操作系统是计算机专业必修的专业基础课程,是考研的必考科目。它的特点是概念多、较抽象和涉及面广,所以无论是大学学习还是考研,很多同学都把它当做一块硬骨头,其实只要我们掌握正确的学习方法,操作系统课程还是非常容易理解和掌握的,终在考研时取得到高分。

    67214 人正在学习 去看看 任铄

Linux操作系统有着各种各样的有点,它有着MS-DOS、OS/2、Windows等其他操作系统的有点,又摒弃他们的缺点。

Linux可以与MS-DOS、OS/2、Windows等其他操作系统共存于同一台机器上。它们均为操作系统,具有一些共性,但是互相之间各有特色,有所区别。 

目前运行在PC机上的操作系统主要有Microsoft的MS-DOS、Windows、Windows NT、IBM的OS/2等。早期的PC机用户普遍使用MS-DOS,因为这种操作系统对机器的硬件配置要求不高,而随着计算机硬件技术的飞速发展,硬件设备价格越来越低,人们可以相对容易地提高计算机的硬件配置,于是开始使用Windows、Windows NT等具有图形界面的操作系统。Linux是新近被人们所关注的操作系统,它正在逐渐为PC机的用户所接受。那么,linux系统命令与其他操作系统的主要区别是什么呢?下面从两个方面加以论述。 

首先看一下Linux与MS-DOS之间的区别。 

在同一系统上运行Linux和MS-DOS已很普遍,就发挥处理器功能来说,MS-DOS没有完全实现x86处理器的功能,而Linux完全在处理器保护模式下运行,并且开发了处理器的所有特性。Linux可以直接访问计算机内的所有可用内存,提供完整的Unix接口。而MS-DOS只支持部分Unix的接口。 

就使用费用而言,Linux和MS-DOS是两种完全不同的实体。与其他商业操作系统相比,MS-DOS价格比较便宜,而且在PC机用户中有很大的占有率,任何其他PC机操作系统都很难达到MS-DOS的普及程度,因为其他操作系统的费用对大多数PC机用户来说都是一个不小的负担。Linux是免费的,用户可以从internet上或者其他途径获得它的版本,而且可以任意使用,不用考虑费用问题。 

就操作系统的功能来说,MS-DOS是单任务的操作系统,一旦用户运行了一个MS-DOS的应用程序,它就独占了系统的资源,用户不可能再同时运行其他应用程序。而Linux是多任务的操作系统,用户可以同时运行多个应用程序。 

再看一下Linux与OS/2、Windows、Windows NT之间的区别。 

从发展的背景看,Linux与其他操作系统的区别是,Linux是从一个比较成熟的操作系统发展而来的,而其他操作系统,如Windows NT等,都是自成体系,无对应的相依托的操作系统。这一区别使得Linux的用户能大大地从Unix团体贡献中获利。因为Unix是世界上使用最普遍、发展最成熟的操作系统之一,它是七十年代中期发展起来的微机和巨型机的多任务系统,虽然有时接口比较混乱,并缺少相对集中的标准,但还是发展壮大成为了最广泛使用的操作系统之一。无论是Unix的作者还是Unix的用户,都认为只有Unix才是一个真正的操作系统,许多计算机系统(从个人计算机到超级计算机)都存在Unix版本,Unix的用户可以从很多方面得到支持和帮助。因此,Linux做为Unix的一个克隆,同样会得到相应的支持和帮助,直接拥有Unix在用户中建立的牢固的地位。 

从使用费用上看,Linux与其他操作系统的区别在于Linux是一种开放、免费的操作系统,而其他操作系统都是封闭的系统,需要有偿使用。这一区别使得我们能够不用花钱就能得到很多Linux的版本以及为其开发的应用软件。当我们访问Internet时,会发现几乎所有可用的自由软件都能够运行在linux程序设计上。有来自很多软件商的多种Unix实现,Unix的开发、发展商以开放系统的方式推动其标准化,但却没有一个公司来控制这种设计。因此,任何一个软件商(或开拓者)都能在某种Unix实现中实现这些标准。OS/2和Windows NT等操作系统是具有版权的产品,其接口和设计均由某一公司控制,而且只有这些公司才有权实现其设计,它们是在封闭的环境下发展的。

操作系统基础知识

阅读数 175

没有更多推荐了,返回首页