Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1148241
  • 博文数量: 173
  • 博客积分: 4048
  • 博客等级:
  • 技术积分: 2679
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-12 18:53
文章分类

全部博文(173)

文章存档

2018年(1)

2016年(1)

2013年(1)

2012年(118)

2011年(52)

分类: LINUX

2012-03-07 20:46:32

为了提高文件系统性能,内核的每次读写请求并不是都直接通过驱动程序访问磁盘进行I/O,而是要经过高速缓冲区。如下图所示:

每个高速缓冲块对应一个磁盘块,都为1024B。为管理这些高速缓冲块,内核使用buffer_head数据结构。如下:
struct buffer_head {
       char * b_data;                               /* pointer to data block (1024 bytes) */高速缓冲块指针
       unsigned long b_blocknr;              /* block number */块号
       unsigned short b_dev;                  /* device (0 = free) */数据源的设备号
       unsigned char b_uptodate;           //更新标志:表示数据是否已更新
       unsigned char b_dirt;                    /* 0-clean,1-dirty */修改标志:0未修改,1已修改
       unsigned char b_count;                /* users using this block */使用的用户数
       unsigned char b_lock;                   /* 0 - ok, 1 -locked */ 缓冲区是否被锁定
       struct task_struct * b_wait;           //指向等待该缓冲区解锁的任务
       struct buffer_head * b_prev;         //hash 队列上前一块(用于缓冲区管理)
       struct buffer_head * b_next;         //hash  队列上后一块
       struct buffer_head * b_prev_free; //空闲表上前一块
       struct buffer_head * b_next_free; //空闲表上后一块
};

所有缓冲块头组成双向循环链表:



实际上这个双向链表是一个最近最少使用LRU链表,free_list是该链表最空闲的缓冲块处的头指针。当内核需要缓冲块,而缓冲区中的缓冲块都已被使用时,则需要替换其中的缓冲块,则从free_list开始寻找缓冲块。
为了快速查找需要的磁盘块数据是否已经在缓冲区中存在,即缓冲区中是否有需要的缓冲块。使用hash队列,以设备号和块号作hash,将buffer_head置于各hash队列中。搜索时则直接从对应的hash队列中进行。其结构如图:

因此,内核取得缓冲块的算法如下:
如果指定的缓冲块存在于hash表中,则说明已经得到可用的缓冲块,于是直接返回。
否则就需要在链表中从free_list头指针处开始搜索,即从最近最少使用的缓冲块开始。
对应函数getblk()的流程如下


获得缓冲块后,根据缓冲块中数据是否有效决定是否从磁盘读取数据。
整个获得缓冲区函数bread()流程如下:



详见linux内核完全剖析


阅读(4043) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~