📄 00000004.htm
字号:
要是你可以拦截使用者对某些目录的存取,然後偷天换日一下, 那一定可以 <BR>让系统更有趣. 比如说Mail来的时候通知使用者(不用一直polling), 使用者 <BR>读某个档时就把目前时间印出来, 使用者open /tcp/<service>/<hostname>时, <BR>就产生对<sevice:hostname>的连线,让没有网路知觉的shell,awk程式也可以 <BR>轻松处理网路上的资料. <BR> <BR>本章讨论了两个这样的系统,第一个是watchdogs,这是学生的研究作品, <BR>整合性不足. 4.4 BSD Portal file system才可以算完整解决方案. <BR> <BR>一个新的File System写起来很复杂, 而一般人可能只想在file system <BR>上加点小功能,比如说on-line compression等等. 4.4BSD和SunSoft皆 <BR>提出了Stackable file system的模组化机制,以达到这个目的. <BR>SunSoft的版本在本书写作的时候还在草稿阶段而已.BSD的则是已经放 <BR>入4.4BSD原始码内了. <BR> <BR> <BR>Chapter 12 Kernel Memory Allocation <BR> <BR>本章以後开始讨论到记忆体管理的问题了. Chapter 12讨论kernel <BR>如何管理自己所用的资料结构所使用的记忆体,如 inode的配置等问 <BR>题. Chapter 13,13,15则是讨论kernel的virtual memory管理. 被 <BR>kernel用来放自己的资料结构的记忆体就不能给paging system用, <BR>所以两者之间如何平衡是很重要的. <BR> <BR>本章提了好几个memory allocator. 其中提到C Library的malloc所 <BR>使用的方法值得提出来和大家分享. malloc配置记忆体是所谓的power <BR>of two free lists.把记忆体分成不同的2的次方的大小 <BR>(32,64,128...1024bytes)来管理. 不过allocator保留这些block <BR>的最前面几个byte当作header, 当这块记忆体不用时(free), <BR>则header指向下一个free block, 彼此间是一个list. 而使用中 <BR>时header则指向他所属的list. (比如说大小是32的list), 这样 <BR>子free()才会知道怎麽归还记忆体.如果你有K&R这本书的话, 可 <BR>以翻翻看书上的□例是不是这样子作的. <BR> <BR>power-of-two的配置方式有个致命的缺点, 就是可使用的空间只有 <BR>sizeof(block)-sizeof(header),也就是略小於(32,64,128,...1024). <BR>如果应用程式要一个比如说64bytes的记忆体, 那麽64-block就装不下, <BR>要分配一个128-block才行, 造成浪费.回想一下,你写程式是不是很喜欢 <BR>malloc(128), malloc(512), malloc(1024)呢? 是不是感觉上 <BR>应该对performance比较好呢? 看完这段描述, 那你可能就不会 <BR>这麽想了. 我想,这也是许多人评论不同的c compiler记忆体管 <BR>理优劣的一个地方吧!如果你常自己抓一些source code来安装, <BR>就可以了解为什麽很多作者都弃系统的library不用, <BR>自己提供malloc了吧. <BR> <BR>书上提到power of two的改进法, 称为McKusic-Karels Allocator. <BR>获得4.4BSD和Digital UNIX采用. McKusic-Karels 配置法把一段连 <BR>续的记忆体都切成固定的大小, 比如说32bytes, 那麽使用中的header <BR>就不用指回他所属的list了, 因为由他的位置kernel就可以知道他属 <BR>於哪一国的. <BR> <BR>皆下来提到Buddy System, 这是和power of two不太一样的配置法, <BR>优点是free()之後的临接空间可以聚合起来成为较大的可用空间. <BR>(power-of-two这方面作的并不好). 这个优点称为coalescing.并 <BR>且Buddy System可以简易的和paging system交换记忆体空间, <BR>使的kernel占用的记忆体空间可以动态的调整. 不过他的performance <BR>不太好, 因为每次release momory,allocator就很贪心的把所有 <BR>临接的记忆体空间并起来, 浪费许多时间. <BR> <BR>SVR4使用了修改过的Buddy演算法 - Lazy Buddy 作为配置kernel <BR>objects的方法. <BR> <BR>Buddy系统和power of two一样, 都是以2^n作为配置记忆体的单位. <BR> <BR>Mach, OSF/1使用了另一种方法, Zone Allocator. 这个配置法不 <BR>再以2^n作为配置单位, 而是以物件为导向来配置.也就是说allocator <BR>从paging系统要来一块记忆体,把他按照object的大小切成n份, <BR>比如说, port资料结构为104 bytes, 那麽mach会把要来的记忆体 <BR>(比如说1KB),分成1024/104块来使用. 这很明显提高了记忆体 <BR>的利用率. 给一个object用的记忆体称为一个zone, 比如说zone <BR>of ports, zone of inodes等等. 不同的object使用不同的zone, <BR>即使他们的大小一样. <BR> <BR>Zone Allocator使用背景的garbage collection程式来回收记忆体. <BR> <BR>本章最令人拍案叫绝的是Solaris 2.4的Slab Allocator. <BR> <BR>Slab allocator和zone allocator 方向差不多, 以object size <BR>当成配置单位,但是他更进一步分析记忆体的使用情形. 比如说 <BR>inode好了.首先我们要一块记忆体 - malloc(sizeof(inode)), <BR>然後initialize inode,接著是正常的使用, 使用完毕後便用free() <BR>归还记忆体. Slab allocator注意到free()之後的记忆体的资料 <BR>和刚刚initialize时差不多, 比如说inode的reference count <BR>一定是降为零等等. Kernel有许多资料结构都是还原到和initialize时 <BR>一样的时候才会free掉.再说一个例子, 一个mutex lock initalize时 <BR>是unlock的状态, free时也是unlock的. <BR> <BR>Slab allocator利用这项特性, 事先把所有的(用Mach的语言是zone)初始化, <BR>那麽就可以省下不少initialize的时间. <BR> <BR>另一个slab allocator注意到的问题是cpu cache的使用率.一般的cache演算法是 <BR> <BR> cache location = address % cache_size <BR> <BR>一般的power of two配置法配置的记忆体都会经过align, 并且大多数程式 <BR>的习惯会把最常用的资料栏位放在一个结构的最前面. 这两个效应合在一起, <BR>造成这些栏位互相的清掉彼此的cache. 512kb的cache可能只有部分有作用. <BR>更甚者, 如果主记忆体使用interleave的方式, 比如说SPARC center 2000 <BR>使用两个bus, 较低的256byte使用第一个bus,较高的256byte使用第二个bus, <BR>那麽所有的data可能会集中在第一个bus上, 造成不平衡现象. <BR> <BR>Slab的解决方法是在向paging系统取得一块block之後, (假设为1KB), <BR>Slab把他要用的资料摆在这个block最後面, 假设占y bytes. 假设所 <BR>要配置的是inode, 大小跟前面Mach的例子一样皆是104. 那麽这块记 <BR>忆体可以提供(1024-y)/104个inode. 并且有一些馀数, 也就是剩下 <BR>一些多馀的记忆体.Slab善用这些记忆体, 将之二等分, 一份摆在这 <BR>块记忆体的最前面,一块摆在最後面. 最前面那块称为coloring area. <BR>Slab设法在每次配置的page上使用不同大小的coloring area, 以有效的 <BR>分散资料map到cache中的位置,增加cache rate. <BR> <BR>Allocator Footprint指的是Allocator在配置记忆体的时候将自己, <BR>以及所参考到的资料写到cpu cache/ TLB (translation lookaside <BR>buffer), 在cache/TLB上面产生的"脚印". Allocator在cache/TLB内 <BR>所留下的资料基本上是没有用的, 并且妨碍真正有用的资料留在cache <BR>上. buddy演算法需要参考许多资料才能配置记忆体, 会产生大量的 <BR>"footprint", 导致cache miss增加. McKusick-Karels和zone allocator <BR>的足迹皆很小, 原因是配置记忆体的时候直接从free list上把第一个 <BR>element抓出来而已. 所以一个好的配置法应该使用简单的演算来配置 <BR>物件. Slab也是使用相同的原则, 不论是配置或者是释放,都是简单的 <BR>一两行运算而已,所以foot print也很小. <BR> <BR> <BR>Chapter 13 Virtual Memory <BR> <BR>本章对virtual memory作个通论, 如paging, segmentation, swaping, <BR>virtual memory等等作个介绍, 跟作业系统的书讲的差不多. 然後个案 <BR>讨论了几个热门的CPU的MMU. MIPS R3000比较特别, CPU没有自动处理 <BR>TLB, 而是提供了一堆TLB暂存器让kernel自己玩. <BR> <BR>现代Unix皆使用paging的机制来提供虚拟记忆体. 不过通常CPU对 <BR>paging的机制都不完全. kernel除了维护cpu所需的paging table <BR>之外, 自己还需要维护一份相对应的表格, 以满足所需. <BR> <BR>本章最後讨论了4.3BSD的Virtual Memory系统. 4.3BSD使用cmap[] <BR>的资料结构来辅助paging管理. cmap的方式是在VAX-11的架构下设 <BR>计的, 没有shared memory也没有shared library, 没有memory <BR>mapped file, 没有copy-on-write等等的支援,不胜枚举, 在现代 <BR>已经可以作古了. 不过4.3BSD的架构仍然为日後的发展奠立的良好 <BR>的基础. <BR> <BR>BSD对swap space的处理颇为保守. 要求所有在主记忆体的page <BR>在配置前都必须要先有一块swap space. 所以swap space的大 <BR>小限制了可以执行的程式数量.不过这也保证程式只有在fork或 <BR>exec时才会发生记忆体不足的现象, 而不会执行到一半要被swap <BR>出去, 却找不到swap space可用的窘况.也就是说如果你的电脑有 <BR>64MB的记忆体,但是只划了16MB的记忆体,这样的系统只愿意让你使 <BR>用16MB而已, 这也是有些系统管理的书籍建议你swap space不要比 <BR>main memory小的原因. <BR> <BR> <BR>Chapter 14 The SVR4 VM Architecture <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -