[声明:欢迎转载,转载请注明出自CU ACCESSORY
}
为什么要这样设计呢?因为LINUX的设计目标之一就是应用于服务器。这种情况下,一个SERVICE可能会启动很多进程(线程)来服务不同的CLIENT. 所以FORK设计成快速复制父进程。子进程直接使用父亲的地址空间,只有子进程加载一个新的可执行文件的时候才创建自己的地址空间。
这样节省了创建地址空间这个庞大的开销,使得LINUX的进程创建十分快。不过实际上,这里的进程相对于WINDOWS中的线程,所以同WINDOWS中的线程创建相比,二者的开销应该差不多。
那么如何才能让新的进程加载一个可执行文件呢,这时就要用execv以及相关函数了。所以LINUX中,代替CreateProcess()的函数是fork+execv
3、文件格式 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的开发顺利很多。
4、内核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