⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ul_buffer.cpp

📁 类似Linux操作系统0.11版文件系统的文件系统设计和Windows下的操作程序
💻 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 + -