第三章 数据缓冲区高速缓冲

来源:互联网 发布:交换机网络克隆模式 编辑:程序博客网 时间:2024/05/21 11:09

对文件系统的一切存取操作,内核都能通过每次直接从磁盘上读或写入磁盘实现,但这样的方式受到磁盘传输速率的限制,比如读写速度较慢的磁盘会使系统的响应时间加长、吞吐率降低。为了解决多次读写磁盘所花费的大量时间开销,内核通过保持一个称谓数据缓冲区高速缓冲(buffer cache)的内部数据缓冲区来减小对磁盘的读写频率。


缓冲头部

内核体系结构中高速缓冲模块的位置是在文件子系统与设备驱动程序之间。缓冲区是磁盘块在内存中的拷贝,在同一时刻绝对不允许将一个磁盘块映射到多个缓冲区中,换言之,一个磁盘块只能映射到一个缓冲区中。一个缓冲区由两部分组成:

  1. 磁盘数据存储器数组

  2. 标识该缓冲区的缓冲头部

    缓冲区头部
    (1)设备号:逻辑文件系统号
    (2)块号:磁盘逻辑块号
    (3)状态字节:概括缓冲区当前状态
    (4)指针

缓冲池的结构

内核按最近最少使用算法(NRU)把数据存放于缓冲池中。
缓冲池包含两个重要的数据结构:
空闲表:标识空闲的缓冲区,以双向循环链表链接。
散列队列:每个缓冲区总是存在于一个散列队列中。
再次强调,没有多个缓冲区同时包含一个磁盘块数据的情况。
总结:缓冲池的磁盘块,存在且仅存在于一个散列队列中,并且仅在那个散列队列中驻留一段时间。若缓冲区为空闲状态,便可以存在于空闲表中。

缓冲区的检索

当存取一个磁盘块时,内核使用适当的设备号和块号的组合去找相应的缓冲区,而不是搜索整个缓冲区池。它把缓冲区组织成一个个队列,成为散列队列,散列函数的参数为设备号和块号。

设备号决定从哪个文件系统上读取磁盘块; 块号决定从该文件系统上的哪个磁盘块读取数据。

如果一个进程要从一个文件中读数据,则内核需判定哪一个文件系统包含该文件,以及该文件系统中的哪一块包含该数据。现在确定了文件系统后,内核需要选择从哪一个特定的磁盘块上读取数据。此时,内核首先检查该块是否在缓冲区池中,若不在,则分配给该磁盘块一个空闲的缓冲区;进程向磁盘块写入数据时,操作类似:若该磁盘块不在缓冲区池中,则为该磁盘块分配一个空闲缓冲区。读写磁盘块时使用算法getblk来对池中缓冲区进行分配。

缓冲区的读写

为了读一个磁盘块,进程使用算法getblk在高速缓冲中搜索这个磁盘块。如果它在高速缓冲中,则内核可不必从磁盘上读取该块,通过算法bread读取含有数据的缓冲区中的内容;如果它不在高速缓冲中,则内核调用磁盘驱动程序,用以安排一个读请求,然后进入睡眠,等待I/O事件的完成。


内核只在逻辑上涉及文件系统,不实现逻辑设备与物理设备的映射,而磁盘驱动程序实现逻辑设备和物理设备之间的地址转换。


读磁盘块:在一个进程顺序地读一个文件的时候,较高层次的内核模块(比如文件子系统)可能会预期到对另一个磁盘块的需要,因而该模块异步地请求第二个I/O。为了做到这点内核执行提前读磁盘块算法breada。个人理解:进程在等待第一个读请求的事件的睡眠中,内核预期到对下一个读操作,因而唤醒进程进行下一次的读操作。异步读的时候,内核并不等待第一个读操作完成而提前执行下一次的读操作。(不知正确与否)
写磁盘块:内核首先告知磁盘驱动程序说自己有一个缓冲区的内容应该被输出。磁盘驱动程序调度到该块上一遍进行I/O操作。如果写操作是同步的,则调用写操作的进程进入睡眠直至I/O完成才能被唤醒;如果写操作是异步的,则内核开始写入磁盘,但是进程的唤醒不一定等待I/O完成。当I/O完成时,内核通过算法brelse释放该缓冲区。
注:延迟写和异步写的区别。

  • 异步写时内核立即开始这一写操作,但并不等待这一写操作的完成。写操作完成后,内核将释放该缓冲区。

  • 延迟写时内核则尽可能长时间地推迟写磁盘的操作。

高速缓冲的优点和缺点

  • 缓冲区提供了同一的磁盘存取方法,内核不需要知道I/O的原因。即是说,不论是文件中的数据、索引节点中数据、超级块中数据,内核都是利用缓冲区来进行读写(如果数据不在缓冲区中,则为该磁盘块分配一个缓冲区)。
  • 高速缓冲的使用可以减少磁盘的访问次数,从而提高整个系统的吞吐量,减少响应时间。
  • 缓冲区算法有助于确保文件系统的完整性。
  • 由于延迟写使得内核没有立即把数据写到磁盘上,因此当系统崩溃时可能造成数据丢失。
  • 高速缓冲的使用使得进程读写数据时增加了一次将磁盘数据拷贝到缓冲区或将缓冲区拷贝到磁盘的过程。在I/O量较大的系统中,这样的过程所耗费的时间是远小于进程每次从磁盘块上读取数据所耗费的时间的。
原创粉丝点击