但是通过内核缓冲的方法降低了系统的性能。首先内核必须在内核空间开辟公用的消息缓冲,在很多进程都需要消息传递时,缓冲区将出现溢出情况,并且不同进程改变缓冲区的消息时,使得进程地址空间相互独立的设计思想被变相的破坏了,进程可以通过改变缓冲区中的消息来实现改变其他进程地址空间的内容,这使得微内核Minix 3原本的高可靠性和高安全性设计思想被破坏。其次,消息必须被复制两次,这两次数据拷贝可能耗时很大,拷贝消息n字节的消息必须消耗20+0.75n次CPU指令周期[2],并且还会导致TLB和cache的未命中。
在这里我们提出一种新的设计思路。内核通过将进程A地址空间中的消息映射给B通过这种快速映射来实现消息的传递(见图3)。在映射过程为了防止进程B对进程A中的该页面进行修改而产生的不可靠性,在映射过程中采用了写时拷贝技术。资源的复制是在进程B需要写入时才会进行,在此之前,页面以只读方式共享。它将地址空间上的页的拷贝被推迟到实际发生写入的时候。
这种方法避免了在内核中设置消息缓冲,这也符合了是Minix 3在消息传递采用的聚合原则。
Intel系列CPU的MMU可以采用两级页表,第一级为页目录,大小为4KB,存储在物理页中,每个表项4字节长,共1024个表项。每个表项对应第二级的一个页表,第二级的每一个页表也有1024个表项,每个表项对应一个物理页。由于Minix 3采用了固定大小的消息通信,消息的大小随机器的体系结构的不同会有所不同,但消息大小肯定是在页面大小以内的。因此,一次消息的映射只需要复制一个页表,即4字节而已(见图4)。这种方法对于消息传递所付出的代价是可以忽略的。
3、实验及结果分析
测试所使用的机器配置是:CPU:Intel Celeron 1.7GHZ;Cache:256K;内存:1G。
我们让改进后的Minix 3的测试进程重复执行系统调用,以此来达到频繁切换地址空间与进程间通信的目的。例如getpid系统调用就是一个用户进程到进程管理器的一次进程通信。测试结果如表1。
可以看到,在加入分页机制,对进程间通信和地址空间的切换进行改进后,性能的牺牲仅仅是5-10%左右,但在保证Minix 3原有的稳定性与可靠性的基础上,再次提高了稳定性和可靠性,这是非常值得的。
4、结论
微内核中困扰性能的两大因素主要是进程间通信以及任务切换。除了对进程间通信做出改进以外,也需要对任务切换进行优化。大量的任务切换直接导致了地址空间的转换,而地址空间的切换必然伴随着TLB的刷新,随着TLB容量的增加,TLB的刷新也为地址空间切换的带来了很大的开销,可以设计一种能有效避免TLB刷新的方法。