📄 linux kernel(
字号:
face=宋体 lang=ZH-CN size=3>由不同功能的部分构成,这些部分总体组合构成了</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN size=3>操作系统。</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN size=3>最明显的部分就是</FONT><FONT
size=3>Kernel</FONT><FONT face=宋体 lang=ZH-CN size=3>自身,但是如果没有</FONT><FONT
size=3>shell</FONT><FONT face=宋体 lang=ZH-CN size=3>或</FONT><FONT
size=3>libraries</FONT><FONT face=宋体 lang=ZH-CN size=3>一样没有用处。</P>
<P align=justify> </P>
<P align=justify>为了了解什么是操作系统,看一看在你输入最简单的命令时发生了什么:</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>$ls</P>
<P align=justify>Mail c images perl</P>
<P align=justify>Docs tcl</P>
<P align=justify>$</P></FONT><FONT face=宋体 lang=ZH-CN size=3>
<P align=justify>这里的</FONT><FONT size=3>$</FONT><FONT face=宋体 lang=ZH-CN
size=3>是登录的</FONT><FONT size=3>shell</FONT><FONT face=宋体 lang=ZH-CN
size=3>输出的提示符(此例是</FONT><FONT size=3>bash</FONT><FONT face=宋体 lang=ZH-CN
size=3>):表示</FONT><FONT size=3>shell</FONT><FONT face=宋体 lang=ZH-CN
size=3>在等候你(用户)输入命令。输入</FONT><FONT size=3>ls</FONT><FONT face=宋体 lang=ZH-CN
size=3>引发键盘驱动程序识别输入的字符,键盘驱动程序将识别的字符传递给</FONT><FONT size=3>shell</FONT><FONT
face=宋体 lang=ZH-CN size=3>去处理。</FONT><FONT size=3>shell</FONT><FONT face=宋体
lang=ZH-CN size=3>先查找同名的可执行映象,它找到了</FONT><FONT size=3>/bin/ls, </FONT><FONT
face=宋体 lang=ZH-CN size=3>然后调用核心服务将</FONT><FONT size=3>ls</FONT><FONT face=宋体
lang=ZH-CN size=3>执行程序加载到虚拟内存中并开始执行。</FONT><FONT size=3>ls</FONT><FONT face=宋体
lang=ZH-CN
size=3>执行程序通过执行核心的文件子系统的系统调用查找文件。文件系统可能使用缓存的文件系统信息或通过磁盘设备驱动程序从磁盘上读取文件信息</FONT><FONT
size=3>,</FONT><FONT face=宋体 lang=ZH-CN
size=3>也可能是通过网络设备驱动程序同远程主机交换信息而读取本系统所访问的远程文件的详细信息(文件系统可以通过</FONT><FONT
size=3>NFS</FONT><FONT face=宋体 lang=ZH-CN
size=3>网络文件系统远程安装)。不管文件信息是如何得到的,</FONT><FONT size=3>ls</FONT><FONT face=宋体
lang=ZH-CN size=3>都将信息输出,通过显示驱动程序显示在屏幕上。</P>
<P align=justify> </P>
<P
align=justify>以上的过程看起来相当复杂,但是它说明了即使是最简单的命令也是操作系统各个功能模块之间共同协作的结果,只有这样才能提供给你(用户)一个完整的系统视图。</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>2.2.1 Memory management</FONT><FONT face=宋体 lang=ZH-CN
size=3>(内存管理)</P>
<P align=justify> </P>
<P
align=justify>如果拥有无限的资源,例如内存,那么操作系统所必须做的很多事情可能都是多余的。所有操作系统的一个基本技巧就是让少量的物理内存工作起来好像有相当多的内存。这种表面看起来的大内存叫做虚拟内存,就是当软件运行的时候让它相信它拥有很多内存。系统将内存分为容易处理的页,在系统运行时将这些页交换到硬盘上。而应用软件并不知道,因为操作系统还使用了另一项技术:多进程。</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>2.2.2 Processes (</FONT><FONT face=宋体 lang=ZH-CN
size=3>进程</FONT><FONT size=3>)</P>
<P align=justify> </P></FONT><FONT face=宋体 lang=ZH-CN size=3>
<P align=justify>进程可以看作一个在执行的程序,每一个进程都是正在运行的特定的程序的独立实体。如果你观察一下你的</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>系统,你会发现有很多进程在运行。例如:在我的系统上输入</FONT><FONT size=3>ps </FONT><FONT face=宋体
lang=ZH-CN size=3>显示了以下进程:</P></FONT><FONT size=3>
<P align=justify>$ ps</P>
<P align=justify>PID TTY STAT TIME COMMAND</P>
<P align=justify>158 pRe 1 0:00 -bash</P>
<P align=justify>174 pRe 1 0:00 sh /usr/X11R6/bin/startx</P>
<P align=justify>175 pRe 1 0:00 xinit /usr/X11R6/lib/X11/xinit/xinitrc --</P>
<P align=justify>178 pRe 1 N 0:00 bowman</P>
<P align=justify>182 pRe 1 N 0:01 rxvt -geometry 120x35 -fg white -bg black</P>
<P align=justify>184 pRe 1 < 0:00 xclock -bg grey -geometry -1500-1500
-padding 0</P>
<P align=justify>185 pRe 1 < 0:00 xload -bg grey -geometry -0-0 -label
xload</P>
<P align=justify>187 pp6 1 9:26 /bin/bash</P>
<P align=justify>202 pRe 1 N 0:00 rxvt -geometry 120x35 -fg white -bg black</P>
<P align=justify>203 ppc 2 0:00 /bin/bash</P>
<P align=justify>1796 pRe 1 N 0:00 rxvt -geometry 120x35 -fg white -bg black</P>
<P align=justify>1797 v06 1 0:00 /bin/bash</P>
<P align=justify>3056 pp6 3 < 0:02 emacs intro/introduction.tex</P>
<P align=justify>3270 pp6 3 0:00 ps</P>
<P align=justify>$</P></FONT><FONT face=宋体 lang=ZH-CN size=3>
<P align=justify> </P>
<P align=justify>如果我的系统拥有多个</FONT><FONT size=3>CPU</FONT><FONT face=宋体
lang=ZH-CN size=3>那么每个进程可能(至少在理论上如此)都在不同的</FONT><FONT size=3>CPU</FONT><FONT
face=宋体 lang=ZH-CN
size=3>上运行。不幸的是,只有一个,所以操作系统又使用技巧,在短时间内依次运行每一个进程。这个时间段叫做时间片。这种技巧叫做多进程或调度,它欺骗了每一个进程,好像它们是唯一的进程。进程相互之间受到保护,所以如果一个进程崩溃或不能工作,不会影响其他进程。操作系统通过给每一个进程一个独立的地址空间来实现保护,进程只能访问它自己的地址空间。</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>2.2.3 Device Drivers</FONT><FONT face=宋体 lang=ZH-CN
size=3>(设备驱动程序)</P>
<P align=justify> </P>
<P align=justify>设备驱动程序组成了</FONT><FONT size=3>Linux</FONT><FONT face=宋体
lang=ZH-CN
size=3>核心的主要部分。象操作系统的其他部分一样,它们在一个高优先级的环境下工作,如果发生错误,可能会引发严重问题。设备驱动程序控制了操作系统和它控制的硬件设备之间的交互。比如:文件系统向</FONT><FONT
size=3>IDE</FONT><FONT face=宋体 lang=ZH-CN
size=3>磁盘写数据块是使用通用块设备接口。驱动程序控制细节,并处理和设备相关的部分。设备驱动程序和它驱动的具体的控制器芯片相关,所以,如果你的系统有一个</FONT><FONT
size=3>NCR810</FONT><FONT face=宋体 lang=ZH-CN size=3>的</FONT><FONT
size=3>SCSI</FONT><FONT face=宋体 lang=ZH-CN size=3>控制器,那么你需要</FONT><FONT
size=3>NCR810</FONT><FONT face=宋体 lang=ZH-CN size=3>的驱动程序。</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>2.2.4 The Filesystems</FONT><FONT face=宋体 lang=ZH-CN
size=3>(文件系统)</P>
<P align=justify> </P>
<P align=justify>象</FONT><FONT size=3>Unix</FONT><FONT face=宋体 lang=ZH-CN
size=3>一样,在</FONT><FONT size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>里,系统对独立的文件系统不是用设备标示符来存取(比如驱动器编号或驱动器名称),而是连接成为一个树型结构。</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>在安装新的文件系统时,把它安装到指定的安装目录,比如</FONT><FONT size=3>/mnt/cdrom</FONT><FONT
face=宋体 lang=ZH-CN size=3>,从而合并到这个单一的文件系统树上。</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>的一个重要特征是它支持多种不同的文件系统。这使它非常灵活而且可以和其他操作系统良好共存。</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN size=3>最常用的文件系统是</FONT><FONT
size=3>EXT2</FONT><FONT face=宋体 lang=ZH-CN size=3>,大多数</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN size=3>发布版都支持。</P>
<P align=justify> </P>
<P
align=justify>文件系统将存放在系统硬盘上的文件和目录用可以理解的统一的形式提供给用户,让用户不必考虑文件系统的类型或底层物理设备的特性。</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN size=3>透明的支持多种文件系统(如</FONT><FONT
size=3>MS-DOS</FONT><FONT face=宋体 lang=ZH-CN size=3>和</FONT><FONT
size=3>EXT2</FONT><FONT face=宋体 lang=ZH-CN
size=3>),将所有安装的文件和文件系统集合成为一个虚拟的文件系统。所以,用户和进程通常不需要确切知道所使用的文件所在的文件系统的类型,用就是了。</P>
<P align=justify> </P>
<P align=justify>块设备驱动程序掩盖了物理块设备类型的区别(如</FONT><FONT size=3>IDE</FONT><FONT
face=宋体 lang=ZH-CN size=3>和</FONT><FONT size=3>SCSI</FONT><FONT face=宋体
lang=ZH-CN size=3>)。对于文件系统来讲,物理设备就是线性的数据块的集合。不同设备的块大小可能不同,如软驱一般是</FONT><FONT
size=3>512</FONT><FONT face=宋体 lang=ZH-CN size=3>字节,而</FONT><FONT
size=3>IDE</FONT><FONT face=宋体 lang=ZH-CN size=3>设备通常是</FONT><FONT
size=3>1024</FONT><FONT face=宋体 lang=ZH-CN
size=3>字节,同样,对于系统的用户,这些区别又被掩盖。</FONT><FONT size=3>EXT2</FONT><FONT face=宋体
lang=ZH-CN size=3>文件系统不管它用什么设备,看起来都是一样的。</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>2.3 Kernet Data Structures</FONT><FONT face=宋体 lang=ZH-CN
size=3>(核心数据结构)</P>
<P align=justify> </P>
<P
align=justify>操作系统必须纪录关于系统当前状态的许多信息。如果系统中发生了事情,这些数据结构就必须相应改变以反映当前的实际情况。例如:用户登录到系统中的时候,需要创建一个新的进程。核心必须相应地创建表示此新进程的数据结构,并和表示系统中其他进程的数据结构联系在一起。</P>
<P align=justify> </P>
<P
align=justify>这样的数据结构多数在物理内存中,而且只能由核心和它的子系统访问。数据结构包括数据和指针(其他数据结构或例程的地址)。乍一看,</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>核心所用的数据结构可能非常混乱。其实,每一个数据结构都有其目的,虽然有些数据结构在多个的子系统中都会用到,但是实际上它们比第一次看到时的感觉要简单的多。</P>
<P align=justify> </P>
<P align=justify>理解</FONT><FONT size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>核心的关键在于理解它的数据结构和核心处理这些数据结构所用到的大量的函数。本书以数据结构为基础描述</FONT><FONT
size=3>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>核心。论及每一个核心子系统的算法,处理的方式和它们对核心数据结构的使用。</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>2.3.1 Linked Lists</FONT><FONT face=宋体 lang=ZH-CN
size=3>(连接表)</P>
<P align=justify> </P></FONT><FONT size=3>
<P align=justify>Linux</FONT><FONT face=宋体 lang=ZH-CN
size=3>使用一种软件工程技术将它的数据结构连接在一起。多数情况下它使用链表数据结构。如果每一个数据结构描述一个物体或者发生的事件的单一的实例,比如一个进程或一个网络设备,核心必须能够找出所有的实例。在链表中,根指针包括第一个数据结构或单元的地址,列表中的每一个数据结构包含指向列表下一个元素的指针。最后元素的下一个指针可能使</FONT><FONT
size=3>0</FONT><FONT face=宋体 lang=ZH-CN size=3>或</FONT><FONT
size=3>NULL</FONT><FONT face=宋体 lang=ZH-CN
size=3>,表示这是列表的结尾。在双向链表结构中,每一个元素不仅包括列表中下一个元素的指针,还包括列表中前一个元素的指针。使用双向链表可以比较容易的在列表中间增加或删除元素,但是这需要更多的内存存取。这是典型的操作系统的两难情况:内存存取数还是</FONT><FONT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -