现代操作系统都在各个级别应用了高速缓存的策略,从而可以平滑化物理硬件的访问差异。一般的高速缓存分为两级,cpu 和内存之间一般会设置高速缓存,但是 这一般是硬件实现的,还有一个高速缓存存在于内存和磁盘之间,这个一般由操作系统实现,当然为了给应用程序提供灵活的策略自定义机制,在某些情况下也可以 由应用程序实现高速缓存,比如Oracal ,当然,这必须要求操作系统有直接IO 的机制。先说Linux 吧。
在linux 中,对于文件系统的访问要经过很多层次,第一个经过的就是vfs ,vfs 为不同的文件系统给上层提供了一个统一的文件访问接口,如果要访问一 个文件,在经过vfs 的接口层之后就要访问具体文件的inode 了,再往下就是页高速缓存,页高速缓存描述的对象是页面,但是用户读写的是文件中特定偏移 的数据,这就需要页高速缓存实现从页面到文件偏移的映射,linux 的页高速缓存恰恰就是这么设计的,内核中通过一个叫做基树的数据结构 address_space 来描述页高速缓存,它实现了偏移到页面的映射。在早期的版本中,内核通过一个全局的哈希表来缓存文件页面,那样的话由于全局变 量的原因,锁的争用导致了严重的性能问题,于是为了让设计粒度更加细化,采用了基树,linux 基树的实现使得页高速缓存只和页面和具体文件inode 有 关,而和具体进程没有关系,十分适合共享,而且适合将暂时不用的页面最大化的应用于高速缓存,具体数量只和当前系统负载和页面回收策略相关,如果感兴趣可 以仔细读一下相关代码。下面看看windows 的实现。
windows 的实现和linux 的截然不同,windows 高速缓存的设计理念在于设计一个单独完整的高速缓存,所以它不能和文件系统相关,因为系统层 次越往下分支越多,于是乎,windows 的高速缓存只能在文件系统之上实现,这就体现了windows 和linux 在设计理念上的最大不 同,windows 强调模块化(偏微内核),毕竟它是商业产品,linux 强调效率,这才是黑客们最关心的... 那么是不是就是说linux 的高速缓存就 和文件系统相关呢?你完全可以这么说!怎么说呢,因为不管是ext2 还是ntfs 还是reiserfs ,在内核里面都是一个inode ,这就是vfs 的v 的含义吧,那么怎么区别不同文件系统呢?那完全通过回调函数做到的,想起OO 了吗?内核是java 写的吗?...
接着说windows 高速缓存,windows 高速缓存是大小确定的,并且一次只能映射一个文件,印象中是256k ,如果高速缓存大于256k ,不知道能 否映射多个文件,这些都是IO 管理器主管的。当引用一个文件时,高速缓存管理器就会把它映射到仅仅256k 的缓存中,如果用玩了,那么就会解除一个文件映 射,从而映射新文件,如果文件已经被映射进高速缓存,并且所需要的数据块不在高速缓存,那么由页面错误来处理一切,结果就是数据块被复制进高速缓存,实际 上高速缓存管理器并不知道数据是否在缓存,而由缺页来协助完成数据引进,所以,每次数据都是从高速缓存被复制进用户空间的(1. 本来就在缓存;2. 由缺页 处理复制进缓存)。这么看来windows 的高速缓存和某些cpu 的高速缓存实现很像,它作为一个你不得不经过的层次(数据都是有高速缓存得到的),在 io 管理器下工作着。
windows 的高速缓存看起来更加具有模块化品质,它很平滑得集成进了io 管理框架,想去除或修改非常简单,而linux 的高速缓存好像是和inode 揉在一起的,但是效率呢?反正我市不希望每次都在文件不在缓存的情况下产生一次缺页中断,linux 的设计更好一些,最起码,它可以减少一次次缺页处理。
这是我发现两大系统很不同的一个方面,孰优孰劣,我认为这个问题很愚蠢,只能分类讨论,就像我前面引用的文章,你能说出古罗马和汉朝的战争结果吗?
今天下午看了一下《陆地和海洋》,收获颇深!