Linux 2.6内核新变化[3]

[入库:2005年9月19日] [更新:2007年3月25日]

本文简介:

  另外一个变化是引入了 TLS(Thread Local Storage)系统调用,这个调用允许分配一个或多个 GDT(Global Descriptor Table)

条目,作为线程注册表。每个 CPU 有一个 GDT,每个条目对应一个线程。这样就可以实现一个不受创建的线程数限制的1:1线程模型

(因为每一个新的内核线程都是为一个用户线程而创建)。2.4内核中每个处理器最多只能支持8,192个线程。


  系统调用 clone 被扩展,以优化线程的创建。如果 CLONE_PARENT_SETID 标志被设置,内核会把线程ID存储在一个给定的内存

位置,如果当线程结束时 CLONE_CLEARID 标志被设置,内核就会把那个内存位置清空。这有助于用户级的内存管理去识别没有使

用的内存块。同样,对线程注册表的信号安全加载的支持也已经融入到这个体系中。当 pthread_join 发生时由内核根据线程ID来完

成 Futex(fast user space mutex)。(要了解futex的更多信息,请参阅参考资料).


  POSIX信号处理在内核空间中完成。一个信号会传递给进程中一个可用的线程;销毁信号会终止整个进程。停止和继续信号也会影响

整个进程,这样就可以实现对多线程进程的工作控制。


  引入了退出系统调用的一个变种,叫做 exit_group(),这个系统调用终止整个进程和它的线程。此外,退出处理通过引入O(1)算法得

到了改进,从而可以在两秒内终止一个具有成千上万个线程的进程(而在2.4内核中完成同样的事情需要15分钟)。


  修改了 proc 文件系统,不再报告所有的线程而只是报告原始的线程。这样就避免了 /proc 报告速度的下降。内核保证原始的线程在

所有其他线程终止之前不会终止。





虚拟内存的变化


  从虚拟内存的角度来看,新内核融合了 Rik van Riel 的 r-map (反向映射,reverse mapping)技术,

将显著改善虚拟内存 在一定程度负载下的性能。


  为了理解反向映射技术,让我们来首先简单了解 Linux 虚拟内存系统的一些基本原理。


  Linux 内核工作于虚拟内存模式:每一个虚拟页对应一个相应的系统内存的物理页。虚拟页和物理页之间的

地址转换由硬件的页表来完成。对于一个特定的虚拟页,根据一条页表记录可以找到对应的物理页,或者是

页无法找到的提示(说明存在一个页错误)。但是这种"虚拟到物理"的页映射不是总是一一对应的:多个虚

拟页(被不同的进程共享的页)有可能指向同一个物理页。在这种情况下,每个共享进程的页记录将有指向

对应物理页的映射。如果有类似这样的情况,当内核想要释放特定的物理页时,事情会变得复杂,因为它必

须遍历所有的进程页表记录来查找指向这个物理页的引用;它只能在引用数达到0时才能释放这个物理页,

因为它没有别的办法可以知道是不是还存在实际指向这个页的引用。这样当负载较高时会让虚拟内存变得

非常慢。


  反向地址映射补丁通过在结构页引入一个叫做 pte_chain 的数据结构(物理页结构)来解决这一问题。

pte_chain 是一个指向页的 PTE 的简单链接列表,可以返回特定的被引用页的 PTE 列表。页释放一下

子变得非常简单了。 不过,在这种模式中存在一个指针开销。系统中的每一个结构页都必须有一个额外的

用于 pte_chain 的结构。在一个256M内存的系统中,有64K个物理页,这样就需要有 64KB * (sizeof(struct pte_chain))

的内存被分配用于 pte_chain 的结构――一个很可观的数字。


  有一些可以解决这个问题的技术,包括从结构页中删掉 wait_queue_head_t 域(用于对页的独占访问)。

因为这个等待队列极少用到,所以在 rmap 补丁中实现了一个更小的队列,通过哈希队列来找到正确的等待队列。


  尽管如此,rmap 的性能――尤其是处于高负载的高端系统――相对于2.4内核的虚拟内存系统还是有了显著的提高。


  Linux 2.6的驱动程序移植


  2.6内核给驱动程序开发人员带来了一系列非常有意义的变化。本节重点介绍将驱动程序从2.4内核移植到2.6内核的

一些重要方面。


  首先,相对于2.4来说,改进了内核编译系统,从而获得更快的编译速度。加入了改进的图形化工具:make xconfig

(需要Qt库)和make gconfig(需要GTK库)。



 当使用make时自动创建 arch-zImage 和模块

  使用 make -jN 可以进行并行的 make

  make 默认的不是冗余方式(可以通过设置 KBUILD_VERBOSE=1 或者使用 make V=1来设置为冗余方式)

  make subdir/ 将编译 subdir/ 及其子目录下的所有文件

  make help 将提供 make 目标支持

  在任何一个阶段都不需要再运行 make dep


  内核模块加载器也在2.5中完全被重新实现,这意味着模块编译机制相对于2.4有了很大不同。需要一组新的模

    块工具来完成模块的加载和缷载 (他们的下载链接可以在参考资料中找到),原来的2.4所用的 makefile 在2.6

    下不能再用。


  新的内核模块加载器是由 Rusty Russel 开发的。它使用内核编译机制,产生一个 .ko(内核目标文件,kernel

    object)模块目标文件而不是一个 .o 模块目标文件。内核编译系统首先编译这些模块,并将其连接成为 vermagic.o。

     这一过程在目标模块创建了一个特定部分,以记录使用的编译器版本号,内核版本号,是否使用内核抢占等信息。


  现在让我们来看一个例子,分析一下新的内核编译系统如何来编译并加载一个简单的模块。这个模块是一个“hello

     world”模块,代码和2.4模块代码基本类似,只是 module_init 和 module_exit 要换成 init_module 和 cleanup_module

本文关键:Linux 2.6内核新变化
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top