📄 ul_buffer.cpp
字号:
/*
* UNIX Like (UL)文件系统高速缓冲模块
*/
#include "stdafx.h"
#include "UL_FileSys.h"
#include "UL_Buffer.h"
#include "UL_Super.h"
#include "BlkDev.h"
// 下面宏定义用于同时判断缓冲区的修改标志和锁定标志
// 并且定义修改标志的权重要比锁定标志大。
#define BADNESS(bh) (((bh)->b_dirt<<1)+(bh)->b_lock)
struct buffer_head start_buffer[NR_BUFFERS];
char bh_data[NR_BUFFERS*1024];
//// 等待指定缓冲区解锁。
static inline void wait_on_buffer (struct buffer_head *bh)
{
}
//// 在高速缓冲中寻找给定设备和指定块的缓冲区块。
// 如果找到则返回缓冲区块的指针,否则返回NULL。
static struct buffer_head *find_buffer (int dev, int block)
{
struct buffer_head *tmp;
tmp = start_buffer;
for (int i=0; i<NR_BUFFERS; i++, tmp++)
if (tmp->b_dev == dev && tmp->b_blocknr == block)
return tmp;
return NULL;
}
struct buffer_head * get_hash_table (int dev, int block)
{
struct buffer_head *bh;
if (!(bh = find_buffer (dev, block)))
return NULL;
bh->b_count++;
return bh;
}
//// 取高速缓冲中指定的缓冲区。
// 检查所指定的缓冲区是否已经在高速缓冲中,如果不在,就需要在高速缓冲中建立一个对应的新项。
// 返回相应缓冲区头指针。
struct buffer_head * getblk (int dev, int block)
{
struct buffer_head *tmp, *bh;
int i;
// 搜索hash 表,如果指定块已经在高速缓冲中,则返回对应缓冲区头指针,退出。
if (bh = get_hash_table (dev, block))
return bh;
// 扫描空闲数据块链表,寻找空闲缓冲区。
// 首先让tmp 指向空闲链表的第一个空闲缓冲区头。
tmp = start_buffer;
for (i=0; i<NR_BUFFERS; i++, tmp++)
{
// 如果该缓冲区正被使用(引用计数不等于0),则继续扫描下一项。
if (tmp->b_count)
continue;
// 如果缓冲头指针bh 为空,或者tmp 所指缓冲头的标志(修改、锁定)权重小于bh 头标志的权重,
// 则让bh 指向该tmp 缓冲区头。如果该tmp 缓冲区头表明缓冲区既没有修改也没有锁定标志置位,
// 则说明已为指定设备上的块取得对应的高速缓冲区,则退出循环。
/*
if (!bh || BADNESS (tmp) < BADNESS (bh))
{
bh = tmp;
if (!BADNESS (tmp))
break;
}
*/
// 如果已经修改
if (tmp->b_dirt)
{
ll_rw_block (WRITE, tmp); // 产生写设备块请求。
}
bh = tmp;
break;
}
if (i==NR_BUFFERS)
{
panic ("getblk: i==NR_BUFFERS\n");
while(1);
}
// 如果所有缓冲区都正被使用(所有缓冲区的头部引用计数都>0)
// 错误
if (!bh)
panic ("getblk: 缓冲区满\n");
wait_on_buffer (bh);
/* OK,最终我们知道该缓冲区是指定参数的唯一一块,*/
/* 而且还没有被使用(b_count=0),未被上锁(b_lock=0),并且是干净的(未被修改的)*/
// 于是让我们占用此缓冲区。置引用计数为1,复位修改标志和有效(更新)标志。
bh->b_count = 1;
bh->b_dirt = 0;
bh->b_uptodate = 0;
bh->b_dev = dev;
bh->b_blocknr = block;
return bh;
}
//// 释放指定的缓冲区
void brelse (struct buffer_head *buf)
{
if (!buf) return;
wait_on_buffer (buf);
if (!(buf->b_count--))
panic ("brelse: 试图释放空闲缓冲区\n");
// wake_up (&buffer_wait);
}
//// 从指定设备上读取指定的数据块。
struct buffer_head *bread (int dev, int block)
{
struct buffer_head *bh;
// 在高速缓冲中申请一块缓冲区。如果返回值是NULL 指针,表示内核出错,死机。
if (!(bh = getblk (dev, block)))
panic ("bread: getblk 返回值为 NULL\n");
// 如果该缓冲区中的数据是有效的(已更新的)可以直接使用,则返回。
if (bh->b_uptodate)
return bh;
// 否则调用ll_rw_block()函数,产生读设备块请求。并等待缓冲区解锁。
ll_rw_block (READ, bh);
wait_on_buffer (bh);
// 如果该缓冲区已更新,则返回缓冲区头指针,退出。
if (bh->b_uptodate)
return bh;
// 否则表明读设备操作失败,释放该缓冲区,返回NULL 指针,退出。
brelse (bh);
return NULL;
}
//// 缓冲区初始化函数。
void buffer_init ()
{
struct buffer_head* bh = start_buffer;
char *pdata = bh_data;
for (int i=0; i<NR_BUFFERS; i++, bh++, pdata+=1024)
{
bh->b_dev = 0; // 使用该缓冲区的设备号。
bh->b_dirt = 0; // 脏标志,也即缓冲区修改标志。
bh->b_count = 0; // 该缓冲区引用计数。
bh->b_lock = 0; // 缓冲区锁定标志。
bh->b_uptodate = 0; // 缓冲区更新标志(或称数据有效标志)
bh->b_data = pdata;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -