Linux 0.11源码阅读笔记-高速缓冲
阅读原文时间:2023年07月08日阅读:6

高速缓冲

高速缓冲区是内存中的一块内存,在块设备与内核其它程序之间起着一个桥梁作用。内核程序如果需要访问块设备中的数据,都需要经过高速缓冲区来间接的操作

高速缓冲区结构

高速缓冲区被划分为1k大小的缓冲块,与磁盘块大小一致。高速缓冲区主要包含两部分内容,缓冲块头结构(buffer_head,bh)及其对应的缓冲块。缓冲块用于缓存磁盘数据,并且具有一个缓冲块头结构;缓冲块头结构保存对应缓冲块的元数据。高速缓冲采用hash表和包含所有缓冲块的链表进行操作管理。

缓冲块头结构用于建立内存缓冲块和磁盘被缓冲数据块之间的映射关系,并记录一些访问状态、管理属性。缓冲块头结构具有指向缓冲块的指针,并记录有被缓冲磁盘块的信息,包括磁盘块所属设备号,磁盘块号等,从而建立起映射关系。

  • 高速缓冲区结构

  • buffer_head信息

空闲缓冲块

使用双向链表串联空闲缓冲块头结构,使用b_prev_free和b_next_free指针域。

已分配缓冲块

为支持对缓冲区的高速访问,使用hash表管理已分配缓冲块。根据被缓冲磁盘块所在设备号和逻辑块号,分配的缓冲块被哈希到哈希表中,哈希函数为:(设备号^逻辑块号)Mod 307。使用拉链发处理hash冲突,具有相同哈希值的缓冲块被组织为双向链表,使用b_pre、b_next指针域

当用户程序读文件时会发生什么?

1)read函数读文件时,底层进一步调用bread函数读设备的磁盘块数据。

2)bread调用getblk函数获取缓冲块,若缓冲块数据有效,则直接返回缓冲块头指针;否则调用块设备低层块读写函数ll_rw_block()读写数据到缓冲块中,并等待在该缓冲区上。

唤醒:设备完成读写后,会发出中断,中断处理程序会唤醒等待在缓冲块上的进程

  • 内核程序块设备访问操作

  • 缓冲区管理函数之间的层次关系

    • bread、breada、bread_page:用于读磁盘块,使用方式略有区别
    • getblk:获取缓冲块,可能是之前便已分配的缓冲块,存在有效数据;返回的块也可能是新分配的缓冲块,需要进一步调用ll_rw_block函数读写磁盘块数据。
    • get_hash_table_find_buffer等:在hash表和双向链表中查找、分配缓冲块。
    • brelse:释放缓冲块

  • 高速缓冲区用于解决CPU速度和磁盘读写速度不匹配的问题,可提高磁盘访问效率
  • 空闲缓冲区管理:高速缓冲区像内存和磁盘一样,被划分为固定的块,使用缓冲块头结构(类似inode节点)记录缓冲块元数据,使用双向链表管理空闲数据库。
  • 分配缓冲区管理:高速缓冲区使用hash表+双向链表管理已分配的缓冲块。
  • 等待队列:需要从磁盘加载磁盘块数据到缓冲块时,进程将睡眠在缓冲块等待队列上。
  • 唤醒机制:磁盘设备完成读数据后,向CPU发出中断,中断处理程序负责唤醒缓冲区等待队列上的进程。