Linux 核心--10.文件系统( 八 )



如果在cache中找到了此inode则它的count值递增以表示用户增加了一个,同时文件操作将继续进行 。否则必须找到一个空闲VFS inode以便文件系统能从内存中读取此inode 。VFS有许多种选择来取得空闲inode 。如果系统可以分配多个VFS inode则它将按如下步骤进行:首先分配核心页面并将其打碎成新的空闲inode并将其放入inode链表中 。系统所有的VFS inode都被放到由first_inode指向的链表和inode散列表中 。如果系统已经拥有所有inode, 则它必须找到便于重新使用的inode 。那些inode最好count记数为0;因为这种inode没有谁在使用 。很重要的VFS inode,如文件系统的根inode,其count 域总是大于0,所以它所使用的inode是不能被重新使用的 。一旦找到可重用inode则应清除之: 其VFS inode可能为dirty,必须要写入到文件系统中或者需要加锁,此时系统必须等到解锁时才能继续运行 。

找到新的VFS inode后必须调用文件系统相关例程使用从底层实际文件系统中读出的内容填充它 。在填充过程 中,此新VFS inode的count记数为1并被加锁以排斥其它进程对它的使用直到此inode包含有效信息为止 。

为了取得真正需要的VFS inode,文件系统可能需要存取几类其它inode 。我们读取一个目录时虽然只需要最后一级目录但是所有的中间目录也被读了出来 。由于使用了VFS inode cache,较少使用的inode将被丢弃而较多使用的inode将保存在cache中 。


9.2.9目录 Cache
为了加速对常用目录的访问,VFS维护着一个目录入口cache 。

当在实际文件系统寻找目录时,有关此目录的细节将被存入目录cache中 。当再次寻找此目录时,例如在此目录中列文件名或打开文件,则这些信息就可以在目录cache中找到 。在实际实现中只有短目录入口(最多15个字 符)被缓存,这是因为那些较短目录名的目录正是使用最频繁的 。例如/usr/X11R6/bin这个短目录经常被X server所使用 。

目录cache也由散列表组成,每个入口指向具有相同散列值的目录cache人口链表 。散列函数使用包含此文件系统的设备号以及目录名称来计算在此散列表中的偏移值或者索引值, 这样能很快找到被缓存的目录 。如果在cache中的搜寻消耗的时间太长或者甚至没有找到则使用此cache用处不大 。

为了保证cache的有效性和及时更新,VFS保存着一个最近最少使用(LRU)的目录cache人口链表 。当首次查找此目录时其目录入口被首次放入cache中并添加到第一级LRU链表的尾部 。在已经充满的cache 中它代替位于LRU链表最前端的现存入口 。此目录入口被再次使用时它将被放到第二级LRU cache链表的最后 。此时需要将位于第二级LRU cache链表的最前端的那个替换掉 。入口在链表前端的唯一原因是它们已经很久没被访问过了 。如果被访问过那么它们将位于此链表的尾部附近 。位于第二级LRU cache链表中的入口要比位于第一级LRU cache链表中的安全一些 。


9.3The Buffer Cache





图9.7 Buffer Cache示意图

操纵已安装文件系统将产生大量对此块设备的读写请求 。这些块读写请求都是通过标准核心例程调用以buffer_head结构形式传递到设备驱动中 。它们提供了设备驱动所需的所有信息:表示设备的设备标志符以及请求的块号 。所有块设备都被看成相同块大小的线性块集合 。为了加速对物理块设备的访问,Linux 使用了一个块buffer cache 。系统中全部的块缓冲,包括那些没使用过的新缓冲都保存在此buffer cache中 。这个cache被多个物理块设备共享;任何时刻此cache中都有许多属于不同系统块设备且状态不同的块缓冲 。如果有效数据可以从buffer cache中找到则将节省大量访问物理设备的时间 。任何对块设备读写的块缓冲都被放入此cache中 。随时间的变化有些块缓冲可能将会被此cache中删除以为更需要它的缓冲腾出空间,如果它被频繁使用则可以一直保存在此cache中 。