Linux与Windows内核Compare

(~.~从win切换到linux,刚开始总有那么点不舒服。。) html

本文转自:http://www.2cto.com/os/201203/121539.html linux


我以为两者最大的区别在于WINDOWS是个商业软件,而LINUX是开源软件。商业软件的好处是能够集中一大批人力物力作一件事情。容易统一,兼容(由于客户需求)。而开源的好处在于灵活,开放。
 
在下面的比较中,我通常先介绍下WINDOWS的,而后再介绍LINUX的。
 
一、观念:商业VS 开源
 
WINDOWS是个商业软件,它的源码是保密的. 固然,其余非MS的人也仍是有机会看到源码的. 若是你和MS 签定一个NDA(NON DISCLOSURE AGREEMENT),那么你也有可能拿到WINDOWS代码.
 
言规正传,我以为商业也仍是有好处的。好比兼容性好,我之前用WDM写一个驱动,最多改下编译选项就能够在WIN 98, WIN 2K, WIN XP下运行。十分方便。而若是换成LINUX,那么你只好祈祷不一样的内核版本之间没改那些你用到的头文件,函数接口。不然就要改代码了。
 
同时,开源的好处是适合学习,十分灵活。我以为LINUX十分适合学校,学生。由于开源,当你发现不明白的地方的时候,能够直接去看源码(还记得RTFS? )。看不懂还能够到论坛上问。而对于WINDOWS,你想了解它的内部机制就只好GOOGLE,而后祈祷了。比较好的一个资源是MSDN下面的一个杂志,其中有一个主题叫UNDER THE HOOD, 或者搜搜BUGSLAYER 也能够。这2个专题的做者Matt Pietrek和John Robbins都是大牛级的人物。
 
顺便说下UNDER THE HOOD 这个名字自己。之前一直不太理解,由于查字典的话,HOOD 的意思也就是个盖子。那么盖子下面有啥呢?为啥要看盖子下面呢?
 
来到美国以后,我渐渐明白了。HOOD 在这里应该理解为汽车的引擎盖。在美国,汽车是很广泛的。若是你开车,可是历来没打开过引擎盖,那么说明你只会用,而不了解汽车内部。那么若是你打开盖子看看呢?就能够看到不少内部细节,好比发动机啥的了。
 
在美国这个汽车王国,不少软件术语和汽车有关,由于人们平常生活中对汽车也很了解。好比“引擎”这个词,之前玩3D游戏的时候,常会看到介绍说,本游戏采用了最新的3D引擎。啥意思呢?就是游戏最核心的部分(汽车引擎)已经升级了。不是只把外面的人物形象改了下而已。
 
另外,开源软件也常常用汽车来类比。开源意外着你买了车(软件)后,能够随便拿到一个修理厂去修。也就是什么人均可以改,只要他懂。而COPY RIGHT 软件呢,就是你买了车,可是引擎盖子是锁着的,坏了只能去生产厂家修,其余人修不了。若是万一辈子产厂家不想修或者不会修呢?那你就只能认命了。
 
扯得有点远了,打住。
 
1.一、发布:2进制VS 源码
 
这里主要讨论下WINDOWS和LINUX在发布程序采用的不一样的形式和观念,这些和前面的商业仍是开源的基本观念是联系在一块儿的。
 
在WINDOWS 世界,安装程序几乎所有都是以二进制形式发布的。也就是说,用户下载了一个程序,而后双击,一路NEXT,NEXT,NEXT就能够了。这个方法很适合初学者。在LINUX世界也有相似的机制,好比YUM, APT-GET 等。不过YUM和APT-GET都是比较晚才出现的,在那以前,在LINUX世界安装程序要更麻烦些。
 
有的时候,LINUX的YUM, APT-GET还不够用。好比有的人写的一个小软件,没有放到这些大的公共的库里面。这时,你就会发现他们通常提供一个或者一堆源文件,而后须要使用者本身下载,“编译”,安装。这也就是LINUX世界常见的源代码发布的形式。
 
一开始的时候,十分不习惯LINUX的这种发布形式。用惯了WINDOWS的双击安装,总以为LINUX的安装很麻烦,又要本身./CONFIGURE, MAKE, MAKE INSTALL. 万一这个软件又依赖于其余的库,那么又要本身去找那些库,万一那些库又依赖其余的库...... 另外,各类库的版本也是一个问题,万一不兼容,那么又要找一个兼容的。
 
为何LINUX世界这么多源代码发布呢?为何WINDOWS世界流行2进制文件发布,而不是源代码呢?关于后者,很好解释,由于WINDOWS那边不少源代码都是商业秘密,是不公开的。同时,WINDOWS的程序用到的那些库在通常的系统里都装好了。因此2进制发布可行,也十分方便。
 
关于前一个问题,我以为源代码发布的一个好处是能够在编译的时候进行一些优化和设置。好比一样的代码,在32或64位平台下编译的时候能够进行适当的优化。另外,用户也能够在编译的时候设置一些开关,这样在编译期间的优化通常要好于运行时间的优化。
 
不过源代码发布的一个坏处就是对使用者要求较高。若是运行configue,make命令顺利的话还好。若是万一不顺利,要本身改下头文件啥的,无疑是通常的使用者没法作到的。另外库之间的依赖关系若是是人手工处理的话也十分麻烦。好在LINUX世界后来有了YUM APT-GET之类的包管理系统。大多数软件均可以很方便的安装了。
 
二、进程及其建立CreateProcess VS fork+execv
 
在WINDOWS世界,建立进程最经常使用的WIN 32 API 是CreateProcess以及相关函数。这个函数须要一堆参数(WINDOWS API 的特色),不过不少参数能够简单的用NULL, TRUE OR FALSE来表示。另外,你直接告诉它要执行的是哪一个文件。
 
到了LINUX世界,我模糊的知道fork是用来建立一个新进程的。可是当我看fork的函数说明的时候,呆住了。由于fork不须要任何参数。习惯了CreateProcess 的10来个参数,忽然换成一个不要任何参数的函数,感受很奇妙。一方面以为彷佛事情简单了不少,不用去把10来个参数的每一个意思都搞明白。另一方面又很疑惑,我怎么告诉它我要执行某个文件呢?
 
后来才知道,LINUX中的进程的含义和WINDOWS中是不同的。LINUX中的进程自己是能够执行的。而WINDOWS中,进程只是表示一个资源的拥有体,是不能执行的。要执行的话,必定须要一个线程。这也部分解释了为何CreateProcess中为啥必定要传入要执行的文件的名字。
 
而fork的含义是把进程自己CLONE一个新的出来。也就是说,FORK以后,父进程和子进程都执行一样的一段代码。若是想区分的话,能够根据FORK的返回值来区分。引用一段fork的说明:
 
On success, the PID of the child process is returned in the parent's thread of execution, and a 0 is returned in the child's thread of execution.
 
同时在LINUX程序中,常见的写法以下:
int pid;
pid = fork();
switch (pid)
{
  case 0: //I am the child
 
  ;
  case -1: //failed.
 
  ;
  default: //I am the parent
 
 
}
 
 
为何要这样设计呢?由于LINUX的设计目标之一就是应用于服务器。这种状况下,一个SERVICE可能会启动不少进程(线程)来服务不一样的CLIENT. 因此FORK设计成快速复制父进程。子进程直接使用父亲的地址空间,只有子进程加载一个新的可执行文件的时候才建立本身的地址空间。
 
这样节省了建立地址空间这个庞大的开销,使得LINUX的进程建立十分快。不过实际上,这里的进程相对于WINDOWS中的线程,因此同WINDOWS中的线程建立相比,两者的开销应该差很少。
 
那么如何才能让新的进程加载一个可执行文件呢,这时就要用execv以及相关函数了。因此LINUX中,代替CreateProcess()的函数是fork+execv
 
三、文件格式PE VS ELF
 
WINDOWS中的可执行文件格式是PE。到了LINUX就变成了ELF。2者有类似的地方,好比都分红几个SECTION,包含代码段,数据段等。可是2个又不同。使得从一个转到另一个的人不得不从新学习下。有点象在国内开惯了车的人,到了香港或者英国开车,虽然也是4个轮子一个方向盘,可是一个靠左行驶,一个靠右。老是须要些时间来习惯。
 
那么为啥LINUX不能和WINDOWS用一样的文件格式呢?我以为可能的缘由有几个。首先多是2个差很少同时在设计的,彼此不知道对方的存在。因此也无法一方压倒一方。另一个可能的缘由是PE格式最开始仍是保密的(后来MS公开了PE的SPEC),因此即便LINUX想直接用PE都不行。
 
顺便说下,MS OFFICE 的文档格式之前也是保密的,直到最近(好像是2008年)才公开。但愿这可使得OPEN OFFICE的开发顺利不少。
 
四、内核API:固定VS 非固定
 
WINDOWS内核有一套固定的API,并且向后兼容。这使得WINDOWS 驱动的开发人员在不一样版本之间移植时变得很容易。好比我用WDM (WINDOWS DEVICE MODEL) 开发一个驱动,最多改下编译选项就能够在WIN 98, 2K, XP, 2003 下使用。VISTA 我以为也许均可以。
 
而LINUX没有固定的内核API。2.4版本的内核模块在2.6几乎很大多是不能兼容的。要移植的话,不仅是改个编译选项,而是要改一堆的头文件和实现文件等。而麻烦的是,即便都是2.6内核,不一样的小版本之间也有些不一样。若是你的内核模块恰好用到了变化的部分,那么也只好从新学习,而后改本身的头文件或者实现文件了。
 
固定内核API的好处是兼容性好,坏处是包袱比较大,不得不随时支持老的,也许是过期的接口。好比WINDOWS内核里有WDM 一套API, 可是又有网卡专用的NDIS 一套API. 实际上2套API的不少设计目标是重合的。那么为何有2个呢?由于NDIS是先出来的,为了兼容性,必定要支持。而NDIS又只针对网卡,因此又出来了WDM。
 
不固定API的坏处是升级很麻烦,外围的内核模块维护者很辛苦。好处是能够随时采用更新的设计。
 
5. WINDOWS与LINUX中的中断处理比较
 
5.1不一样之处:
 
在WINDOWS中,有一个IRQL (注意不是IRQ)的概念。最先的时候,我觉得是CPU设计里就包括了这个东东。后来看INTEL CPU手册,发现彷佛没有。最近又看了一遍WINDOWS INTERALS 4TH。感受这个东西应该是包括在PIC OR APIC里面的(关于APIC,能够看我之前的帖子)。对于X86-32,硬件设备的IRQ于IRQL之间的关系是:IRQL= 27-IRQ。引入IRQL的动机彷佛是这样的:当CPU运行在低IRQL时,若是来了一个高IRQL对应的中断,那么低的中断的ISR是会被高的ISR抢过去的。就是说低的ISR又被一个更高级的ISR中断了。这样的好处是优先级高的ISR能够更快的获得响应。
 
另外,在具体实现中,因为操做PIC OR APCI改IRQL是比较费时的,因此WINDOWS是尽可能不去直接操做硬件,而是等到万不得已的时候才改。
 
在LINUX中,彷佛没有相似IRQL这样的观念。就我目前看过的书和代码来看,LINUX中的ISR或者是KERNLE最可能是操做下CPU上的中断标志位(IF)来开启或者关闭中断。也就是说,要么中断全开,要么全关。
 
从这一点来看,LINUX在这部分的设计上比WINDOWS简单。
 
5.2 类似之处:
 
WINDOWS和LINUX彷佛都把中断分红了2部分。在LINUX中叫ISR(仍是其余?)和BOTTOM HALF。而WINODWS中,DPC(Deferred Procedure Calls)和APC(Asynchronous Procedure Calls)就很是相似BOTTOM HALF。两者把中断分红两部分的动机是差很少的。都是为了把ISR搞得越快越好。LINUX中,在ISR里通常关中断,因此时间太长的话,其余中断就得不到响应。WINDOWS中,ISR跑在一个很高的IRQL里面,一样会阻塞其余IRQL比较低的任务。
 
LINUX中的BOTTOM HALF 又能够分为TASKLET 和SOFIRQ。两者的主要区别是复杂度和并发性(CONCURRENCY)。下面COPY自<UNDERSTANDING LINUX NETWORK INTERNALS>一书。
Tasklet: Only one instance of each tasklet can run at any time. Different tasklets can run concurrently on different CPUs.
Softirq: Only one instance of each softirq can run at the same time on a CPU. However, the same softirq can run on different CPUs concurrentlyOnly one instance of each softirq can run at the same time on a CPU. However, the same softirq can run on different CPUs concurrently.
 
WINDOWS中的DPC有点相似TASKLET和SOFTIRQ。DPC是系统范围内的,而且运行在DPC IRQL。是一个相似中断上下文的环境(INTERRUPT CONTEXT)。APC和DPC的区别是运行在更低级别的APC IRQL。另外,APC是针对每个线程的。执行在某个线程环境中。主要目的也是把一部分事情放到之后去执行。APC又分为KERNEL APC 和USER APC。APC这个观念在LINUX中彷佛没有相似的?至少我还没想到。
 
5.3 参考文献:
1.        WINDOWS INTERALS 4TH
2.        UNDERSTANDING LINUX NETWORK INTERNALS, 2005
 
 
UNICODE VS ASCII
KERNEL 4M/4K MIXED PAGE VS 4K PAGE
FS SEGMENT VS NO FS
GDI VS XWINDOWS
IRP VS FUNCTION POINTER
 
 
六、注册表VS 普通文件
     windows下的注册表在内核模式下的全部进程及线程均可以访问到,均可以修改,很方便对系统配置的修改。而linux下没有注册表的概念,系统配置必须在镜像产生前就配置好了(makeconfig)。所以相比之下,Linux不适合动态地定制系统功能,而windows适合快速修改配置,实现系统的功能定制。
 
2、一致的地方
 
WINDOWS和LINUX不少地方又很类似。我以为基本缘由有2个。一个是2者都继续了一部分UNIX中的东西。另一个是2者都主要基于X86体系结构。固然2者也都支持不少其余体系结构,特别是LINUX。
 
我下面主要讨论在X86体系下一致的地方。
 
一、观念
一切皆文件。
 
二、内核映射:2G:2G, 1G:3G. 线性映射
 
三、SOCKET
 
四、DEVICE DRIVER OR KERNEL MODULE
 
五、系统调用,中断 windows