📄 8.htm
字号:
保证Linux健壮性和安全性的唯一一个最重要的因素是其开放的开发过程,它可以被看作 <br>
是一种广泛而严格的检查。内核中的每一行代码、每一个改变都会很快由世界上数不清的 <br>
程序员检验。还有一些程序员专门负责寻找和报告潜在的缺陷—他们这样做完全是出于自 <br>
己的个人爱好,因为他们也希望自己的Linux系统能够健壮安全。以前检查中所没有发现 <br>
的缺陷可以通过这类人的努力来定位、修复,而这种修复又合并进主开发树以使所有的人 <br>
都能够受益。安全警告和缺陷报告通常在几天甚至几个小时内就能够得到处理和修复。 <br>
Linux可能并不一定是现有的最安全的操作系统(很多人认为这项桂冠应该属于OpenBSD, <br>
它是一个以安全性为主要目标的Unix变种),但是它是一个有力的竞争者。而且Linux健 <br>
壮性远没有发展到尽头。 <br>
3.1.5 速度 <br>
这个术语自己就可以说明问题。速度几乎是最重要的衡量标准,虽然其等级比健壮性、安 <br>
全性和(在有些时候)兼容性的等级要低。然而它却是代码最直观的几个方面之一。 <br>
Linux内核代码经过了彻底的优化,而最经常使用的部分—例如调度,则是优化工作的重 <br>
点。几乎在任何时候都有一些不可思议的代码,这是由于这种方式的执行速度比较快(这 <br>
并不总是很明显,但是你经常不得不通过自己的试验来对这种优化代码进行确认)。虽然 <br>
有时一些更直接的实现方法速度也很快,但是我所见过的这种情况很少。 <br>
在某些情况下,本书推荐用可读性更好的代码来替代那些打着速度的名义而被故意扭曲了 <br>
的代码。虽然速度是一个设计目标,但我基本上只在以下两种情况时才会这样做:a) 在 <br>
所考虑的问题中,速度明显不是关键问题 b) 没有其他的办法。 <br>
3.2 内核体系结构初识 <br>
图3-1是一种类Unix操作系统的相当标准的视图,实际上,更细致地说,该图能够说明所 <br>
有期望具有平台无关特性的操作系统。它着重强调了内核的两个特性: <br>
* 内核将应用程序和硬件分离开来。 <br>
* 部分内核是体系结构和硬件特有的,而部分内核则是可移植的。 <br>
第一点我们在前面章节中已经讨论清楚了,在这里没有必要重复说明。第二点,也就是与 <br>
体系结构无关和与体系结构相关代码的内容对于我们的讨论比较有意义。内核通过使用与 <br>
处理用户应用程序相同的技巧来实现部分可移植性。这也就是说,如同内核把用户应用程 <br>
序和硬件分离一样,部分内核将会因为与硬件的联系而同其他内核分离开来。通过这种分 <br>
离,用户应用程序和部分内核都成为可移植的。 <br>
虽然这通常并不能够使得内核本身更清楚,但是源程序代码的体系结构无关部分通常定义 <br>
了与低层,也就是体系结构相关部分(或假定)的接口。作为一个简单的例子,内存管理 <br>
代码中的体系结构无关部分假定只要包含特定的头文件就可以获得合适的PAGE_SIZE 宏( <br>
参见10791行)的定义,该宏定义了系统的内存管理硬件用于分割系统地址空间的内存块 <br>
的大小(参见第8章)。体系结构无关代码并不关心宏的确切定义,而把这些问题都留给 <br>
体系结构相关代码去处理(顺便一提,这比到处使用#ifdef/#endif程序块来定义平台相 <br>
关代码要清晰易懂得多)。 <br>
图3-1 内核体系结构基本结构图 <br>
这样,内核向新的体系结构的移植就转变成为确认这些特性及在新内核上实现它们的问题 <br>
。 <br>
另外,用户应用程序的可移植性还可以通过它和内核的中间层次—标准C库(libc)—的 <br>
协助来实现。应用程序实际上从不和内核直接通讯,而只通过libc来实现。图3-1中显示 <br>
应用程序和内核直接通讯的唯一原因在于它们能够和内核通讯。虽然在实际上应用程序并 <br>
不同内核直接通讯—这样做是毫无意义的。通过直接和内核通讯所能处理的问题都可以通 <br>
过使用libc实现,而且更容易。 <br>
libc和内核通讯的方式是体系结构相关的(这和图中有一点矛盾),libc负责将用户代码 <br>
从实现细节中解放出来。有趣的是,甚至大部分libc都不了解这些细节。大部分的libc, <br>
例如atoi和rand的实现,都根本不需要和内核进行通讯。剩余的大部分libc,例如printf <br>
函数,在涉及到内核之前或之后就已经处理了大量的工作(printf必需首先解释格式化字 <br>
符串,分析相应参数,设定打印方法,在临时内部缓冲器中记录预期输出。直到此时它才 <br>
调用底层系统,调用write来实际打印该缓冲区)。其他部分的libc 则只是相应系统调用 <br>
的简单代理。因而一旦发生函数调用时,它们会立即调用内核相应函数以完成主要工作。 <br>
在最低层次上,大部分libc通过单通道同内核进行交流,而它们所使用的机制将在第5章 <br>
进行详细介绍。 <br>
由于这种设计,所有的用户应用程序,甚至大部分的C库,都是通过体系结构无关的方式 <br>
和内核通讯的。 <br>
3.3 内核体系结构的深入了解 <br>
图3-2显示了内核概念化的一种可能方式。该图和区分内核的体系结构无关及体系结构相 <br>
关的方法有所不同,它是一种更具有普遍性的结构视图。在“Kernel”框内的本书中有所 <br>
涉及的内核部分都用括号注明了相应的章节编号。虽然有关对称多处理(SMP)的支持也 <br>
属于本书的范围,但是在这里我们却没有标明章号。部分原因在于相当多的SMP代码广泛 <br>
地分布于整个内核中,因此很难将它与某一个模块联系起来。同样,对于内核初始化的支 <br>
持也属于本书的范围,但是也没有标明章号。这样做是因为从设计的观点上看,该问题并 <br>
不重要。最后,虽然在图中我们将第6章和“进程间通讯”框联系在一起,但是该章只涉 <br>
及一部分进程间通讯的内容。 <br>
图3-2 详细的内核体系结构图 <br>
进程和内核的交互通常需要通过如下步骤: <br>
1) 用户应用程序调用系统调用,通常是使用libc。 <br>
2) 该调用被内核的system_call函数截获(第5章,171行),此后该函数会将调用请求转 <br>
发给另外的执行请求的内核函数。 <br>
3) 该函数随即和相关内部代码模块建立通讯,而这些模块还可能需要和其他的代码模块 <br>
或者底层硬件通讯。 <br>
4) 结果按照同样的路径依次返回。 <br>
然而,并不是所有内核和进程间的交互都是由进程发起的。内核有时也会自行决定同哪个 <br>
进程交互,例如通过释放信号或者简单的采用直接杀死进程的方法终止该进程的执行(如 <br>
当进程用完所有可用的CPU时间片),以便使其他进程有机会运行。这些交互过程在该图 <br>
中并没有表示,主要是因为它们通常都只是内核对自己的内部数据结构的修改(信号传递 <br>
对于这种规则来说是一个例外)。 <br>
<br>
<br>
<br>
-- <br>
※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.196.22] <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="index.htm">上一层</a>][<a href="9.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -