龙芯开源社区

 找回密码
 注册新用户(newuser)
查看: 23108|回复: 107

赞~Linux兼容内核项目:龙井!

[复制链接]
发表于 2009-3-7 08:51:55 | 显示全部楼层 |阅读模式
本帖最后由 joki 于 2010-6-7 10:52 编辑

转自:http://www.longene.org/  
      
   Linux兼容内核自2009年1月起,正式使用项目Unix名称Longene,中文别名“龙井”。
   兼容内核是一个自由、开源的操作系统项目,目的是要把Linux的内核扩充成一个既支持Linux应用、也支持Windows应用,既支持Linux设备驱动、也支持Windows设备驱动的兼容内核;使用户可以直接在Linux操作系统上高效运行Windows应用。
   通过兼容内核,我们希望原来习惯于windows操作习惯的用户可以在Linux上延续他们的操作习惯。用户购买的第三方软件可以变成与操作系统无关,对于用户来说,本来是一旦购买了Windows的应用软件,从此只能选择Windows操作系统,而现在却还可以有选择,这对于Linux当然是意义重大,可以提高桌面Linux的市场竞争力。
   兼容内核开发组是由浙大网新资助的开源项目,我们将遵守GPL规定,公开那些按规定应予公开的源代码。我们欢迎世界各地的广大网友与爱好者的参与,形成一个Linux兼容内核的开源社区.
   我们欢迎海内外高手加盟项目组,成为专职的Linux兼容内核开发人员。浙大网新将维持一支专职的开发团队,采取专职与业余相结合的开发方针。条件成熟的时候,我们将邀请若干专家组成一个技术委员会,以指导本项目的进行。

Linux兼容内核开发路线图

短期计划
2009年2月,将提供针对主流发行版的Linux兼容内核安装包 。
中期计划
实现所有win32系统调用,真正体现Linux兼容内核在兼容性和效率上的优势。
长期计划
实现Windows设备驱动框架与设备驱动支撑界面。


以下是部分程序运行截图:

星际争霸


大富翁6


Photoshop


WPS


IE浏览器



      内容很多,下面引述三篇资料。全部摘自www.longene.org网站。个人觉得这也是个发展方向,而且也具备了一定的实用性。虽然目前在龙芯上还无法直接使用,但还是建议龙梦可以考虑与之合作,等到龙芯3、龙芯2G上的DBT2成熟后移植上去,或许可以助龙芯市场推广一臂之力。

------------------------------------------------------------------------------------------------------------------------
Longene-0.3.0 发布
Longene-0.3.0已于2010.5.31发布,本版本彻底摆脱了对wineserver进程的依赖,是一个具有里程碑意义的版本,当然,目前还存在一些Bug,有待在今后的版本中改进。
 楼主| 发表于 2009-3-7 08:56:56 | 显示全部楼层

开发Linux兼容内核的策略与路线

毛德操

   笔者自从提出Linux兼容内核的构想以后,听到了不少反响。其中支持者固然不乏其人,如开源软件推进联盟主席陆首群先生、倪光南院士、还有OSDL的平野正信先生,都是支持的。但是无庸讳言,对此不以为然的意见也有不少。有趣的是,这些不以为然的意见往往分成两个极端。一个极端说,Linux兼容内核要达到的目标已经达到了,因此根本就不用多此一举。说已经达到,是因为在用户空间我们已经有了Wine,而NdisWrapper则已经解决了把Windows设备驱动装入Linux内核的问题。另一个极端呢,则是说兼容内核的难度太大,根本就不可能成功,所以只是一个“梦”。显然,在谈论开发路线图之前首先应该回答这两种意见。幸好它们正好互相构成回答。

首先,正如笔者在另几篇文章中所说,Wine只是在逻辑上、功能上基本解决了用Linux内核来模拟/仿真Windows内核的问题,但是性能上是无法令人满意的,而且说基本上解决其实也很勉强。至于NdisWrapper,它所解决的是一些网络设备(网卡)的驱动,而不是普遍意义上的设备驱动。更何况NdisWrapper设备驱动的上层只能是Linux的Socket,而不能与诸多文件操作的系统调用挂上钩。实际上,退一步说,即使NdisWrapper和Wine真的已经分别解决了Windows设备驱动和应用软件在Linux内核上的跨平台运行,也还需要有人把这二者整合起来。有许多公司只是把一些开源软件收集(而不是整合)拢来,做成发行版,不是就号称成了“高科技公司”吗?所以,要使Windows的应用软件和设备驱动能在Linux上高效地运行,从而真正为广大用户所接受,兼容内核的开发应该说是很有必要,而且也不是那么轻而易举。

至于说难度太大,那么Wine和NdisWrapper的存在和发展恰恰为兼容内核技术上的可行性提供了参考。诚然,Wine在某些方面很不理想,但那正是因为要避开内核而导致的后果,许多在用户空间很难解决的问题一到了内核里面就可以豁然开朗。或者可以反过来说,Wine在用户空间都可以基本解决的问题,到了内核里面就更好解决了。当然,涉及内核的设计和编程比之用户空间在难度(复杂度)上要高得多,但是“难”是个相对的概念,谁能说清到底难到什么程度就根本不能做了呢?再说这也毕竟不是登月、不是哥德巴赫猜想。另一方面,Wine所提供的许多高层DLL为兼容内核的实际使用提供了条件,或者可以说是解决了后顾之忧。如果说Wine毕竟不涉及内核,因此还不足为凭,那么NdisWrapper可确实为我们在内核中构建设备驱动框架和支撑界面提供了参考,实质上也是一个可行性证明。

认为难度太大的人还有一个顾虑,就是Windows的代码是不公开的,藏在黑盒子中,光凭几本书能得到多少信息、如何就能开发出跟Windows兼容的内核?这种顾虑当然也有一些道理,但是ReactOS又在这方面给我们提供了参考。ReactOS以零为起点从头开发,Wine只在内核外面做文章,尚且都能在一定程度上达到设计目标,而我们站在它们的肩膀上,又有Linux内核作为原材料,至少条件比他们好多了。

当然,把Wine、NdisWrapper和ReactOS作为参考意味着我们需要吃透、或者至少基本上理解它们的代码。为此笔者将陆续写一些分析文章在本网站上推出,起个抛转引玉的作用。

总之,兼容内核的开发既不是唾手可得,也不是难于上青天,既不能一蹴而就,也不至于遥遥无期。说起来还是那句老话:战略上藐视困难,战术上重视困难。



后发跟进、逐步逼近

我们开发兼容内核不能采取一步到位、而应采取逐步逼近的策略。以系统调用界面为例,我们完全可以先搁置那些用于GUI、即win32k.sys的扩充系统调用,即便是对于248个常规系统调用也可以分期分批地实现。实际上,我们甚至并无必要追求一个完整的实现。工程上有一个所谓20/80原理,说是20%的工作量往往可以实现80%的功能,而剩下的20%功能却往往需要80%的工作量才能实现。如果我们的兼容内核可以支持80%的Windows应用,剩下的20%慢慢从长计议也无不可。再说,Windows本身也在发展,今天还是“完整”的实现,明天就可能是不完整的了。所以,我们可以采取在一定距离后面跟进的策略。只要Windows还存在、还在发展,这样的跟进就永远不会完。这种后发跟进、逐步逼近的策略决定了我们的开发必定是一个螺旋式的渐进开发过程。就是说:从不同成分之间的关系看,是螺旋式的发展;从同一成分内部看,则是渐进的发展。

那么,这个螺旋式渐进开发过程的起点是什么呢?起点就是Linux+Wine。随着开发的进行,Linux的内核逐渐变成兼容内核,我们姑且以Linux+表示;而Wine则逐渐演变成一个按Windows系统调用界面定制并且优化了的Wine,我们姑且称之为Wine’。所以整个开发过程就是:

(Linux + Wine) => … => … => (Linux+ + Wine’)

起点Linux+Wine显然是可以运行的,开发过程中的每一步都实现一组有限的目标,每一步的结果都应该是一个可以运行的、更逼近Windows的、可以发行的版本。

对Linux内核的修改原则上以动态安装模块的形式实现,尽可能不改变Linux内核原有的代码,必要时当然也可以打一下补丁。



兼容内核开发的主体是一个框架、两个界面。如果按它们在内核中的位置从上到下排序,那就是:系统调用界面,设备驱动框架,以及设备驱动支撑界面。下面分别加以讨论。



系统调用界面的开发

    系统调用界面的实现有个“门槛”,那就是内核的进入/退出机制,即系统调用时的空间切换机制,不跨过这道门槛就谈不上系统调用界面。不过这个机制的实现并不复杂,因为我们要实现的本质上是Linux内核上的系统调用,从而这实际上就是Linux系统调用的空间切换机制,所不同的只是:

l         Linux原有的系统调用都是通过指令“int 0x80”进入内核的;现在需要为Windows系统调用添上通过指令“int 0x2e”进入内核。

l         Linux原来有个系统调用跳转表,这是一个以Linux系统调用号为下标的函数指针数组;现在需要添上一个Windows的系统调用跳转表,就是以Windows系统调用号为下标的函数指针数组;以后还要再添上一个用于GUI的扩充系统调用跳转表。

可见,这道门槛的实现并不困难。

有了(系统调用时)内核的进入/退出机制,就可以来考虑系统调用界面本身、即系统调用内核函数的集合了。对于Win2k,这就是“Windows NT/2000 Native API Reference”等参考书中所述的二百多个函数。这些函数的实现实际上构成了Windows的文件系统、I/O子系统、进程管理子系统、内存管理子系统,等等。

这里的工作量可就大了,但是可以(也应该)分期分批地予以实现。
l         248个系统调用,数量上与Linux相当。
l         系统空间的进入/退出可以重用Linux的相应代码。
l         进程/线程管理。需要融合两个系统的进程/线程管理机制。
l         进程间通信(包括LPC)。基本上可以嫁接到Linux的相应机制上。
l         存储管理。需要扩充Linux的内存管理介面。
l         文件系统。基本上可以嫁接到Linux的文件系统上。

l         设备驱动。连接到WDM设备驱动框架。

不光是分期分批,就是同一个系统调用也可能需要分几次来完成。有的系统调用有很多可选项,其中有些可选项实际上很少用到。对这样的系统调用,我们就可以先实现其基本功能,然后慢慢完善。

怎样实现这些系统调用内核函数呢?

l         有些系统调用可以嫁接到相应的Linux系统调用。

l         有些系统调用可以部分地重用相应Linux系统调用的代码。

l         有些系统调用在Linux中没有对应物,需要借助Linux内核中的低层函数予以实现。

l         可以借鉴Wine的代码,在一定程度上是把Wine的部分代码移入内核并加以优化。

显然,这个系统调用界面上的文件系统应该嫁接到Linux的文件系统,I/O子系统属于我们要实现的Windows设备驱动框架,进程管理子系统应该嫁接到Linux的进程管理,内存管理子系统应该嫁接到Linux的内存管理,如此等等。

Wine中的底层四大件,即kernel32.dll、user32.dll、gdi32.dll、以及ntdll.dll,原来把所有的系统调用都引向Linux系统调用。随着开发的进展,每实现一个Windows系统调用,就应该在Wine这一层上把原先的系统调用“重定向”到这个Windows系统调用上来。为此,可以对DLL的装入/连接机制加以扩充,以实现“虚拟连接”、即重定向的功能。例如,可以在装入/连接下层DLL时对于需要从下层DLL引入的每一个函数都先检查一个映射文件,看是否需要把这个函数重定向到另一个DLL文件中的另一个函数名。这样,每实现一个Windows系统调用以后,只要修改这个映射文件,并提供另一组底层DLL就可以了。发展到最后,Wine原有的底层DLL就为新的(同名)DLL所取代。这时候,Wine就变成了Wine’。

如前所述,这些系统调用函数可以分期分批实现,其中首先需要实现的是与文件系统和设备驱动有关的系统调用,以便在此基础上搭建Windows设备驱动框架。

除常规的系统调用外,还有一个专用于图形界面(GUI)的扩充系统调用界面,这是因为微软把原先在用户空间实现的GUI支持(类似于X11)移到了内核中,成为一个动态安装模块win32k.sys。这个扩充系统调用界面与常规界面合用同一个进入/退出机制,只是系统调用号全都大于1000。为此,内核中另外需要一个函数跳转表。至于具体系统调用函数的实现,则基本上就是把X11服务进程移植到内核中来,对此我们可以暂时搁置,留待将来再来讨论和实现。



设备驱动框架的开发

基本的设备驱动框架对应着Win2k内核中的I/O管理,以及电源管理、即插即用等机制,也涉及部分对象管理、系统配置、和安全管理方面的功能。其中最主要的是WDM层次式设备驱动机制的实现。这个框架上面与有关文件操作的系统调用(open(),close(),read(),write(),ioctl()等)相衔接,中间实现基于“IO请求包”IRP(IO Request Packet)的设备驱动机制,下面则融入Linux内核的中断响应/服务机制、包括“软中断”即bh函数的执行机制。主要包括:

l         设备驱动程序的动态装入和连接。

l         IRP的生成和传递、以及设备驱动程序的启动、同步、和终结。

l         将设备驱动程序的中断服务登记嫁接到Linux的中断机制上,将设备驱动程序所关心的Windows内核运行状态映射到Linux内核的运行状态上。

l         将设备驱动程序的DPC请求嫁接到Linux的bh函数机制上。



基本设备驱动框架的实现基本上是个“有”与“无”的问题,一旦这个框架成了形,这方面剩下的工作就不很多了。所以,设备驱动框架的实现“门槛”比较高,技术上的难度也相对较大。不过,我们有ReactOS的代码和NdisWrapper的部分代码可资借鉴。

此外,网络设备(网卡)、即NDIS设备的驱动既有其特殊性,又应该看作是Windows设备驱动的一部分,所以设备驱动框架的实现应该包含NDIS的实现。不过这倒是得来全不费功夫,NdisWrapper的代码基本上可以直接加以利用。



    设备驱动框架的开发与系统调用界面的开发并不一定是顺序的。在系统调用界面上有关文件操作的系统调用尚未实现之前,不妨先借用Linux的有关系统调用作为对特殊设备或/proc节点的驱动,就像在大桥尚未造好之前先架一座便桥一样。



基本的设备驱动框架到位以后,如果单纯从技术角度看,所有的.sys文件(即Windows的设备驱动模块)就都可以装入Linux内核运行。但是,有些.sys模块是由微软连同其操作系统捆绑发行的,微软拥有这些.sys文件的版权,Linux的用户不能直接拿过来用。这一类.sys模块基本上都是用于一些标准的、基本的、常用的外部设备,总的来说可以分成几个大类(class),例如磁盘、USB、图形设备、网络设备等等,它们的调用界面既有公共的部分,又各有其特殊之处。一般而言,Linux实际上已经具备相应的功能,只是需要将Linux内核(包括设备驱动模块)中的这些函数和数据结构与具体.sys的调用界面之间架起桥梁。这一部分工作在形式上与系统调用界面和/或设备驱动界面的实现有相似之处,并且也像系统调用界面的实现那样可以从Wine+Linux开始,例如Wine结合内核中HPFS和NTFS的实现实际上就是把Linux的磁盘文件驱动适配到了Windows的磁盘文件访问。

但是也可能有一些微软的.sys模块在Linux内核中找不到对应物,那就需要仿制了。不过这方面的工作没有必要在一开始就进行,而可以推迟到实现了基本的设备驱动框架,并且部分地实现了两个界面以后再回过来渐进地开发。
 楼主| 发表于 2009-3-7 08:58:43 | 显示全部楼层
设备驱动支撑界面的开发

根据微软提供的WinXP DDK,内核中可供设备驱动程序调用的函数(以及全局变量)大约有1000个 (比Win2000多)。在这1000个左右的内核函数中,有一些属于“IO管理器”IoManager和“对象管理器”ObManager,因而属于设备驱动框架,其余的则属于设备驱动界面。

l         有些资源的调用/引用可以映射(重定向)到Linux内核中的对应物上。

l         有些资源的调用/引用可以嫁接(适配)到Linux内核中的对应物上。

l         有些资源的调用/引用需要另加实现。

设备驱动支撑界面的实现也有个起码的门槛。例如分配缓冲区的函数以及相当于spinlock()的函数就是必须的。幸运的是ReactOS和NdisWrapper已经为我们提供了一个基本的支撑函数集合,只是ReactOS的代码不是建立在Linux内核基础上的,所以需要进行一些适配和优化的工作。在这个基本集合的基础上,每多实现一组函数,兼容内核的覆盖面就加大了一些。



从功能的角度看,多数设备驱动界面函数(以及数据结构)在Linux内核中都有对应物,例如,上述用于分配缓冲区的函数以及spinlock()就是,需要做的就是把所需的支撑函数和数据结构落实到相应的Linux内核函数和数据结构上,这里面当然有些适配的工作。也有些函数在Linux内核中没有较为接近的对应物,那就要用Linux内核中的各种素材加以搭建。



从开发的时序看,支撑界面的开发应该在设备驱动框架到位以后,或者至少是二者同步开发。这是因为,离开了设备驱动框架,支撑界面的存在就失去了意义,同时也失去了测试的手段。

其它开发

除一个框架、两个界面以外,还有一些辅助性的开发要做,例如:

l         对Wine的修改

l         某些.sys模块的仿制

l         与注册表的交互

l         Unicode在字符串和文件名中的使用

l         从Windows风格的文件路径名到Linux路径名的映射

l         从Windows风格的设备名到Linux路径名的映射

还可以举出不少。这些工作量合在一起也不容小看,但是从总体上看、从难度和技术含量看、毕竟不是主体。



开发路线图



综合上述各点,我们的开发路线图将大致上如图所示:



首先是准备阶段。在这个阶段中笔者将陆续写出一批文章,对Windows与Linux的异同作一些介绍和比较,对Wine、NdisWrapper、ReactOS的代码作一些介绍和分析,旨在引起网友们的参与和讨论,更欢迎大家到我们网站上发表有关的研究成果和见解。这样,经过一段时间的探讨,参与研发的人对于要做的事情应该可以了然于胸。同时,对于开发的团队,无论是专职的还是业余的,也需要有个形成和组织的过程,我们的网站也需要一段时间来逐步完善。此外,我们还要制定出一个编码标准和一套代码管理办法(包括代码的提交、评审、录用、存档、管理、奖励等各方面的办法),为具体的代码编写做好准备。这么一个准备阶段显然是很有必要的,估计这个阶段将延续到明年1季度,我们希望原则上以春节为界。

开始具体的开发以后,第一件事就是要实现系统调用界面的进入/退出机制。这前面已经讲了。接下来就是设备驱动框架。前者是不可分割的,是有或者无的问题。后者稍微好一些,可以先搞个最低限度的基本框架,再慢慢充实。如果把准备阶段作为整个项目的第一阶段,那么这就是第二阶段。

有了这些以后,下面的第三阶段就可以渐进开发了,所以图中把具体系统调用和设备驱动支撑函数的开发放在一个循环体内。如前所述,这里的每一轮循环都实现一组有限的目标,每一轮的结果都应该是一个可以运行的、更逼近Windows的、可以发行的版本。这个阶段也许永远不会完,永远要循环下去,其结果是愈来愈逼近Windows。另一方面,我们的兼容内核是Linux兼容内核,而Linux也在发展。于是,兼容内核将一边跟随Linux“水涨船高”地发展,一边又愈来愈准确、愈来愈广泛地兼容Windows应用软件。

我们的开发目标是,在一年之内要进入第三阶段并至少完成第一轮循环,即基本实现若干最重要的系统调用和设备驱动支撑函数,取得一些可见的效果。这样,一年内我们就能有一个可以发行的原型。反过来,这个原型又进一步构成整个项目的可行性证明,可以进一步增强开发人员和公众对项目的信心。至于更具体的安排,则有待于准备阶段中进一步的细化。
 楼主| 发表于 2009-3-7 09:00:21 | 显示全部楼层
"一个框架、两个界面"
是Linux兼容内核开发的主体

毛德操

我们开发Linux兼容内核的目标是让Windows应用软件可以直接在这个内核上运行,更确切地说是在以这个内核为核心的操作系统上运行。同时,还要让为Windows而开发的一些设备驱动模块也能装入这个内核运行。这一方面是因为针对Windows开发的设备驱动模块在数量和品种上都远远多于Linux;另一方面是因为有愈来愈多的应用软件需要跟专用的设备驱动模块配套运行,缺了这设备驱动模块就运行不起来。只有同时实现了这两个目标,才能说Linux的内核兼容了Windows内核。那么,为了要达到这两个目标,我们必须对Linux内核作些什么修改和扩充呢?本文就是要对此作一分析,并回答这个问题。

首先,一段封闭的程序、如果既不调用库程序、也不作系统调用,是跟操作系统无关的,只要所在机器的CPU跟这段程序编译时的目标CPU相符就可以了。这是因为,以PC机为例,这段程序编译后所生成的所有指令全都是x86机器指令,而且所有这些指令全都可以正常运行,它的所有跳转指令和子程序调用指令的目标都不会越出这段程序的边界。其次,即使需要调用库程序,只要不直接或间接进行系统调用,就也跟操作系统无关,因为调用库程序在效果上就相当于扩大了这段程序的地盘、推进了它的边界。所以,只要不作直接或间接的系统调用,应用程序的运行就跟操作系统无关,因而可以在任何操作系统上运行。然而,一般而言,这样的程序是不能作为一个独立的应用、独立的进程运行的,因为独立的进程至少总得要输入/输出,这就离不开系统调用了。

那么应用软件怎样进行系统调用呢?大家都知道,这是通过陷阱指令实现的,在x86处理器上是int指令。事实上,Linux内核采用“int 0x80”实现系统调用,而Windows内核采用“int 0x2e”。这首先就使得Windows应用软件不能在Linux内核上运行。试想,Windows应用软件企图通过“int 0x2e”进行系统调用,而Linux内核认为这是非法陷阱指令。由此可见,首先就得使Linux内核接受“int 0x2e”作为系统调用的手段之一。我们真该感谢两个内核的设计者,要是他们当初都选择了0x80、或者都选择了0x2e,那我们现在就不好办了。幸好这二者互不冲突。

由于所有的系统调用都通过同一条陷阱指令进入内核,就需要通过参数“调用号”来区分所要求的具体操作和功能。于是,在通过什么指令进行系统调用以外,还要考虑一共使用了多少个调用号,每个调用号对应着什么操作和功能,需要一些什么参数,结果是什么、怎么返回,有什么副作用等等。所有这些因素合在一起,就构成了一个系统调用界面。当然,Windows的系统调用界面与Linux的不同。而要使Windows软件能在Linux内核上直接运行,就必须让Linux内核也提供一个Windows系统调用界面,否则就只好像Wine那样把Windows软件“嫁接”到Linux系统调用上来。在“嫁接”方面,Wine已经做得很好了,但是我们知道效果还是不理想。

我们说Windows系统调用界面,一方面当然是说它的表现,就是Windows应用软件在内核外面所看到的各个具体系统调用的调用方式、参数、效果、返回的结果、以及副作用。但是,另一方面,更重要的其实是这个界面背后的东西,即这些系统调用的实现,我们在这方面的工作量主要也正在于此。

据“Undocumented Windows 2000 Secrets”介绍,Win2k共有248个常规的系统调用(有逆向工程的结果为证)。其中有的系统调用很简单,或者几乎可以直接用相应的Linux系统调用替代,有的却非常复杂。显然,要从零开始开发出这些系统调用是不大现实的(尽管ReactOS确实在这样做),我们要做的是尽量利用Linux内核中的低层函数来实现这些Windows系统调用。在某种意义上,Wine是在内核外面将Windows应用嫁接到Linux系统调用上,而我们的兼容内核则要在内核里面将Windows系统调用嫁接到Linux的诸多内核函数上。之所以在内核里面嫁接比在内核外面嫁接更好,一方面是因为内核函数的“粒度”较小,内核函数与系统调用之间的关系有点像汇编语言与高级语言之间的关系。另一方面是因为内核空间是统一的,可以提供全局的视野。例如,在内核中可以看到所有进程的进程控制块(PCB);而一出内核,到了用户空间,进程之间就互相隔离了。所以,凡是要求有全局视野的操作,就应该在内核中实现。

除这些常规的系统调用外,Win2k还有639个图形界面(GUI)系统调用。这等于是把X11搬到了内核里面。在WinNT 4.0以前,Windows也像Linux一样,由用户空间的图形服务进程来实现对图形和视窗的操作和管理,那样当然效率比较低。从WinNT 4.0开始,就把图形操作和视窗管理移到了内核里面,成为一个可安装模块win32k.sys。这对于提高图形操作的速度很有意义,否则游戏软件的运行就不会有那么流畅(当然,后来又有了DirectX,进一步提高了图像/图形操作的速度,那是后话)。所以,严格地说,所谓Windows系统调用界面也包括这些图形操作调用。不过实现这些调用的“原材料”不再是Linux内核函数,而是X11中的相关函数。当然,事情有轻重缓急,完全没有必要在一开始就把这六百多个调用也一锅煮。实际上,即使是248个常规系统调用的实现,也没有必要一步到位。



过了系统调用界面这道关,许多系统调用就可以实现了,例如创建进程、取系统时间等等这些,在Linux内核里面就可以完整地实现。但是,一旦涉及输入/输出,涉及设备驱动,就又可能有问题了。问题不在于常规的设备驱动,例如键盘、鼠标、硬盘之类常用设备的驱动Linux内核中本来就有,只要把系统调用嫁接过去就行了。问题在于一些比较特殊的设备,特别是新出现的设备。这些设备的制造商往往只为Windows提供设备驱动模块、即.sys文件。如果不能把这样的.sys模块装入Linux内核并让它们正常运行,对Windows应用的兼容就不可能是完整的。

将.sys模块装入Linux内核不难,因为Linux的动态安装模块与之并无本质的不同。难的是使其在Linux内核中正常运行。要达到这个目标,一是要将装入的模块往上跟有关的系统调用衔接,往下(可能)跟中断响应机制挂上钩;二是要为模块的运行提供一个特定的环境。事实上,.sys模块之所以可以被装入Windows内核并正常运行,正是因为Windows内核满足了这两个条件。显然,现有的Linux内核不具备这样的条件,它所满足的是Linux动态安装模块的运行条件,这跟两个系统调用界面的差别是相似的。所以这也成了兼容内核开发的一个重要组成部分,也代表着相当的工作量。

看看Windows内核怎样来满足这两个条件,就知道我们要做些什么了。

首先是怎样使.sys模块跟有关的系统调用和中断响应挂上钩、接上口。换言之,怎样将.sys模块纳入内核中的设备驱动框架,包括把具体的模块放在框架中的什么位置上,跟上下左右相邻的模块或部件怎么交互。在Windows内核中,这主要是I/O子系统的事,具体主要体现在两个方面:一方面是模块装入以后首先要向I/O子系统登记,或向上一层的设备驱动登记,那也就是间接地向I/O子系统登记。另一方面,当有关的系统调用发生时,正是通过I/O子系统转化成对于具体设备驱动的逐层调用和返回。所以,I/O子系统代表着一个设备驱动框架的主体。不过,I/O子系统并不是设备驱动框架的全部,.sys模块可能还要跟中断响应挂上钩。例如,一个.sys模块中的一部分可能是作为中断服务程序运行的,另一部分可能是作为bh函数(在Windows中称为DPC)运行的,还有一部分则受I/O子系统的驱动。Windows的.sys模块都是针对Windows的设备驱动框架开发的,既然我们要把这些.sys模块装入Linux内核运行,就必须在Linux内核中构建起这么一个框架。具体地,就是要在Linux内核中实现Windows的I/O子系统,Windows的中断响应/服务机制,以及有关的一些辅助性的成分。



Windows设备驱动框架解决了对.sys模块的装入和使用。如果每个模块都是封闭、独立的,不需要环境的支持,那就够了。但是,事实上几乎不存在这种封闭、独立的设备驱动模块,几乎每个模块的运行都需要得倒环境的支持。举例来说,一个设备驱动模块在运行中可能需要分配缓冲区。可是设备驱动模块本身是不具备这个能力的,因为它并不掌握任何可动态分配的内存资源。于是,就只好请求内核予以分配,这就是对环境的依赖。为此,操作系统内核要“引出(export)”大量的内核函数供动态安装模块调用。这个函数集合的大小、以及每个具体函数的调用条件、参数、作用、返回值、副作用,就构成了具体内核的设备驱动支撑界面。显然,不同的内核有不同的设备驱动支撑界面,就好像不同的内核有不同的系统调用界面。要让Windows的.sys模块在Linux内核中正常运行,就必须在Linux内核中提供Windows的设备驱动支撑界面。与系统调用界面不同,Windows设备驱动支撑界面的定义是公开的(否则第三方就无法为其开发设备驱动模块了),定义于Win2k或WinXP的DDK、即“设备驱动开发包”。Win2k的DDK中定义了2000来个支撑函数,但是常用的也就是几百个、甚至更少。当然,微软公开的只是这个界面的定义,而不包括它的实现。

那么,怎样实现这些支撑函数呢?还是老办法,把它们转化成、或者嫁接到相应的Linux设备驱动支撑函数上去。

值得一提的是,Windows对网络设备的驱动另外定义了一个框架,称为NDIS;并专门提供了一个NDIS设备驱动支撑界面,使NDIS设备驱动模块只需要(并且只应该)调用NDIS界面上的支撑函数。这样,网络设备的驱动就自成体系,有了一个大框架中的小框架。不过,无论是NDIS的框架还是支撑界面都比较小,只能算是Windows设备驱动框架和界面的附庸和扩充,而且许多NDIS支撑函数实际上就是一些Windows设备驱动函数的简单包装,所以我们将NDIS归入Windows设备驱动的框架和界面。



综上所述,我们开发Linux兼容内核,主要就是在Linux内核中实现这一个框架和两个界面,就是:Windows设备驱动框架、Windows系统调用界面、以及Windows设备驱动支撑界面。这就是Linux兼容内核开发工作的主体。当然,还有不少零碎的、辅助性的开发工作要做,但相比之下工作量就比较小了。

不过,说“一个框架、两个界面”是开发工作的主体,这是就兼容内核本身而言,而不是就整个操作系统而言。要让Windows应用软件正常运行,在内核外面还需要有一些DLL、即动态连接库的支持,以及一些配套服务进程的支持。如果单纯从技术的角度看问题,那么确实只要有了兼容内核就行了,因为我们可以把Windows上的DLL和配套服务程序都拷贝过来。可是这不仅是个技术问题,更是个法律问题,我们不能去侵犯微软的版权。所以,这些DLL和配套服务程序也都需要开发,幸好Wine已经为我们做了许多这方面的工作,只是需要对其中的四个DLL、即所谓“四大件”作些修改。须知把Windows系统调用嫁接到Linux系统调用的正是这四大件:kernel32.dll、gdi32.dll、user32.dll、还有ntdll.dll,现在则又要使它们回归本来面目,把扭曲了的东西再扭曲回去。

还应看到,Windows的技术和应用本身也在发展,这些发展更多地体现在DLL和服务进程中,例如OLE、COM/DCOM、.NET这些技术大多是通过DLL和服务进程实现的。Wine虽然已经做了很多这样的DLL和服务程序,但是这方面的开发也许永远不会完,不过那是细水长流的事了。
 楼主| 发表于 2009-3-7 09:01:53 | 显示全部楼层
Linux兼容内核
-提高Linux市场竞争力的一个手段

毛德操

虽然Linux在服务器、嵌入式系统、以及高性能计算领域都有不俗的表现,可是在桌面领域的市场占有率很低却是个不争的事实。尤其在中国,如果与Windows相比,桌面Linux的实际使用率几乎可以忽略不计。然而,对于一个现代操作系统而言,桌面应用是其主流;在桌面输了,那就是从总体上输了。

计算机技术的发展史上曾经出现过几次技术上更为先进的产品输给技术上较为落后(但在发展中)的产品的先例,而Linux/Unix和Windows在过去20年间的竞争恰恰是其中最大的一次。关键在于:当技术体现为某种大众化的产品时,就不再是单纯的技术问题了。

笔者不想在这篇短文中分析和总结之所以造成这种局面的原因和教训;更不想在这儿怨天尤人、非议微软的某些受到指责的行为;而只是针对已成之局提出提高Linux市场竞争力的一个手段。这所谓提高,也只是略有提高就好;桌面操作系统的市场那么大,哪怕一个百分点就已经不小了。

那么已成之局是什么呢?最主要的有这么几点:

1)  整整一代人的用户、甚至还包括下一代,都已经习惯于使用Windows。这些人在学校里学的、在培训班里学的、从朋友/同事那儿学的都是Windows,在家里用的、在单位用的、在网吧用的都是Windows,因而它的人机界面和操作方式早已经成为事实上的标准。

2)  Windows的应用软件比Linux丰富得多。Windows有着庞大的、高质量的第三方软件供应。无论是应用软件、中间件、还是系统软件,至少在数量上都是Linux所无可比拟的。事实上,就绝大多数的软件(甚至硬件)供应商的产品来看,其第一个版本几乎肯定是为Windows开发的,然后才有可能想到Linux,实际上还往往置Linux于不顾。

3)  至少在表面上,Windows的售后服务和支持比Linux的好。实际上,这种售后服务和支持绝大部分是针对第三方软件、由第三方软件供应商提供的;可是因为这些软件是在Windows上运行、而且只在Windows上运行,就给人一种印象,似乎Windows的用户得到了支持、而Linux的用户得不到,或者Windows是专业水平的、而Linux是业余水平的。

4)  Windows已经占据计算机应用的主流地位,运行着Linux的计算机必须能与运行着Windows的计算机互连互通,并“无缝”地、按Windows所定义的格式交换各种数据和文件(这一点对于电子商务和电子政务尤为重要)。

实际上,Windows本身的用户界面和操作方式也在变。但是由微软来变则可(不可也得可);而若是别的人来要求用户改变使用习惯,那就难了。

这些问题大家都看到了,但是应对的策略和意见则各有不同。

1)有一种意见和策略认为最主要的是上述的第二条、即Linux上的应用软件太少的问题。既然是应用软件太少,就大力开发应用软件,并与第三方软件商合作、让它们提供Linux版的产品。久而久之,就应该可以使差距降下来。再说,就具体的用户而言,真正需要用到的软件还是很有限的,很可能只是“老三篇”(浏览器、Office、播放器)。反过来,Linux也有不少优点,对用户应该也有些吸引力,更不必刻意去模仿Windows。这样,慢慢就可以缩小差距,从而把用户吸引过来。国外特别是欧美、有不少人持此种意见。但是笔者对此甚感怀疑。据笔者观察,就桌面系统而言,过去十年内这种差距似乎反有扩大的趋势。问题在于,Windows的应用软件也在发展、甚至更快地发展,新的应用又在不断涌现。而第三方软件商的投入与Linux市场竞争力的提高,就成了某种“先有鸡还是先有蛋”的问题。

2) 另一种意见和策略既重视第二条,也重视第一条和第四条,即用户已经习惯于使用Windows及其应用软件、以及与Windows系统交换数据和文件的问题,所以在开发Linux应用软件时很注意与Windows“兼容”,实际上就是使应用软件在外观、功能、操作方式和效果等方面与Windows上的对应软件尽可能一致,让用惯了Windows的人可以毫无困难地转到Linux上来。在这一方面,OpenOffice等软件的开发就很典型。持这种意见的人国外也有不少,国内则更多。说穿了,这就是走“仿制”Windows应用软件的道路。然而,问题在于Windows的应用软件有那么多,又层出不穷,实在是仿不胜仿。

3) “仿制”既然不能很好地解决问题,那就来“嫁接”,就是设法在Linux上直接运行Windows应用软件的二进制映像。在这方面最重要的进展是开源软件Wine的开发。Wine在Linux内核和Windows应用程序之间提供一个适配层。它的上方为Windows应用程序提供Win32 API (实际上也包括16位界面),为应用程序提供以动态连接库为主的Windows运行环境。而其下方,则把本来应该是对Windows内核的系统调用翻译/转化成对Linux内核的系统调用。这样,Windows应用程序实质上是在一个模拟/仿真的Windows内核上运行,而Wine的主要功能就是在Linux内核外面实现对Windows内核的模拟/仿真。不过Wine的设计者不愿意别人认为Wine是个仿真器。这主要是因为“仿真器”这个词容易使人误解,以为是对CPU机器指令的仿真,那是效率非常低的,而Wine的效率确实比普通意义上的仿真要高得多。在过去几年中,Wine一直在稳步地发展,过不多久就会有个较新的版本发布。有几个公司,如Linspire、Xandros等,也在推出基于Wine的产品。一般是同时有两套版本,一套是开源的,另一套则包括一些不公开源码的优化和改进。

4) 还有一种策略是让用户既可以使用Windows,也可以使用Linux。最简单的办法就是所谓双引导,即在同一台机器上装上两个系统、而在引导时加以选择。这样,有些事情适合在Linux上做,就引导Linux,反之则引导Windows。可是这样很不方便,更好的办法就是Vmware所采用的虚拟机技术,就是在Linux上再装一个Windows系统,让Windows作为Linux的一个应用来运行;或者也可以反过来,在Windows上再装一个Linux系统,让Linux作为Windows的一个应用来运行。这种策略最大的问题就是不能摆脱Windows操作系统,因而对于提高Linux市场竞争力的作用也就不大。



在这四种不同的意见和策略中,笔者以为最有效、最有前途的是第三种。说它有效和有前途,是因为至少从理论上说可以把绝大多数的第三方软件变成与操作系统无关。对于第三方软件的购买和使用者来说,本来是一旦买了/用了这种软件就好像定了终身,从此只能用Windows了,而现在却还可以有选择,还可以摆脱Windows,这对于Linux当然是意义重大。

然而,在实践中,情况却并不如想象中那样美妙。主要有这么一些问题:

一、Wine对Windows应用软件的支持面不如想象中那么大,一部分原因是Wine本身的开发有个过程,所以对Win32 API的支持一时还不那么全面。不过这并不是根本性的问题,随着事间的推移会不断改进。事实上,今年的版本比前年的版本就已经充实了不少。

二、虽然Wine不是仿真器,不像仿真器那么低效;但是既然要把原来是对Windows内核的系统调用转化成对Linux内核的系统调用,而两个内核的系统调用又存在着相当程度的差异,那么这种转化难免会使效率有所降低。这有点像是用一种高级语言来实现另一种高级语言,功能是达到了,性能却总不那么好。实际上,许多系统调用本质上是粒度相当大的“宏”操作,在这么大的粒度下很难高效地实现某些微妙的机制。甚至,有些系统调用还可能实际上无法很贴切地翻译成另一组系统调用,以至某些软件在运行时出现不同于Windows上的效果。与上一条相比,这一条是带有根本性的问题。

三、更重要的是,Wine只是在用户空间为Windows应用软件营造了一个运行环境,却没有涉及内核、特别是没有涉及设备驱动程序。这又导致两个方面的问题。首先,许多外部设备厂商现在只为Windows提供设备驱动程序、一般是扩展名为.sys的模块。如果不能把这些设备驱动模块安装到Linux内核中,就意味着Linux一时还不能支持这些外部设备。在这方面,开源项目NdisWrapper已经进行了努力、并取得了不小的成绩;但是它主要是针对一些网卡的驱动程序而开发的,还不够全面。其次,实际上更为重要的是,现在有些应用软件是与某些特定的设备驱动模块配套运行的;缺了内核中的特定设备驱动模块,相应的应用软件也就不能运行了。随着“数字家庭”等等应用和技术的发展,这样的倾向应该还会加剧。传统意义上的内核是公共的,设备驱动属于内核,因而也是公共的;而现在的内核却在朝着动态可定制,或者面向特定应用进行个性化配置的方向在发展。如果把内核比作一盆水,而传统意义上的应用软件像是浮在水面上的鸡蛋,那么现在的有些应用却像个哑铃了。就是说,它的一部分还在水面上、还像个鸡蛋,但是另一部分却在水底,当中有个柄,把两个球状物连成一个整体。显然,缺了内核中的设备驱动这一块,Wine的作用就不完善。而且,二者必须有机地结合起来。

四、Wine对Windows应用软件的支持面不如想象中那么大,还有一部分原因是存在着应用软件绕过Win32 API进入内核的可能。这往往发生在一些老的、特别是16位的软件,以及一些特殊软件。



由此看来,Wine还不能很好地解决问题。正是出于这样的考虑,笔者才提出了“Linux兼容内核”的设想和技术路线。其目的是:将Linux的内核加以扩充,使其既支持Linux本身的应用和设备驱动,又支持Windows的应用和设备驱动,从而成为一个“兼容内核”。要实现这样一个内核,就得在Linux的内核中增加这么几个成分:

l         一个符合Windows设备驱动程序的特征和要求的框架,即Windows设备驱动框架,使得可以把多个Windows设备驱动模块装入内核,并使这些模块间的关系和运行条件跟它们在Windows内核中时相同。

l         一组由Windows内核导出(Export)函数界面(见Windows DDK)定义的导出函数。对于设备驱动程序而言,这些函数就相当于由内核提供的库函数。

l         Windows的系统调用界面。微软并没有公开它的系统调用界面,但是在“Windows NT/2000 Native API Reference”和其他资料中已经揭开了这个秘密。在Linux内核中实现Windows的系统调用界面,就相当于用汇编语言来实现另一种高级语言。这是因为,在内核里面,可以使用的“砖块”就不再是宏观的Linux系统调用,而是Linux的许多微观的内核函数了。



一旦有了这么一个兼容内核,从原理上说只要把Windows的那套DLL(动态连接库)和有关的服务进程软件搬过来,就可以直接运行所有的Windows应用软件了。但是我们当然不能那样干,因为这牵涉到微软的知识产权(第三方提供的DLL当然可以)。所以,有了兼容内核以后,Wine是仍旧需要的,只是再不需要把Windows系统调用翻译/转换成Linux系统调用了,因而将是一个优化了的Wine。这样一个Wine,实际上就是Windows的那些“系统DLL”(以及有关服务进程和一些工具软件)的开源版。

这样,兼容内核的Windows系统调用界面,加上优化了的Wine,这二者的结合在用户空间为Windows应用软件营造出一个运行环境;而设备驱动界面、即DDK所定义的内核导出函数界面,以及设备驱动框架,这二者的结合在系统空间、即内核中为Windows设备驱动程序也营造出一个运行环境。就是说,“哑铃”的两头都照顾到了。

于是,Windows应用所“看到”的就是一个Windows环境,无论是在用户空间还是系统空间都一样,而且这样的环境是由“汇编语言”构筑的,性能上应该与Windows本身所提供的不相上下。这意味着将来Windows软件一般都可以在兼容内核上运行,而且运行时的效果和性能都可以跟在Windows上运行时相仿。既然如此,对于用户来说,改用Linux操作系统就是很现实可行的事了。
发表于 2009-3-7 10:47:41 | 显示全部楼层
我怎么听说毛德操出国了,已经没管这个项目了?
 楼主| 发表于 2009-3-7 10:52:18 | 显示全部楼层
不管老毛在不在,这个项目还在开发
发表于 2009-3-7 12:54:29 | 显示全部楼层
看好这个项目!
发表于 2009-3-7 16:21:11 | 显示全部楼层
听来好像难度不小,支持先
发表于 2009-3-7 17:08:05 | 显示全部楼层
同意楼上意见,不过能运行SC和WPS,我很激动啊
加油

本版积分规则

Archiver|手机版|小黑屋|Lemote Inc.

GMT+8, 2021-1-16 13:32 , Processed in 0.138137 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表