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

📄 blockbuffer.c

📁 参照MINIX3写的操作系统 用GCC+NASM+BOCHS开发
💻 C
字号:

#include "../kernel.h"
#include "FileSystem.h"
#define BUFFER_BASE 0X300000
Buffer FileBuffer[NR_FILE_BUFFER];//(* LPBuffer)0x300000;//文件数据缓冲区

Buffer *HashBuffer[NR_HASH_BUFFER];//文件数据缓冲区哈希表

//extern void SendMessage(int TaskID, Message *pMessage);//发送消息
//extern  void InitVCHDTask();

//FreeHead和FreeTail指向一个空闲队列,采用LRU算法,
//不用的块将会被链入队列头FreeHead,
//从队尾FreeTail中取出最久不用的块
static LPBuffer FreeHead=NULL;//空闲链的头指针

static LPBuffer FreeTail=NULL;//空闲链的尾指针

LPBuffer DirtyLink=NULL;//被修改过的数据的队列头指针

PUBLIC void InitFileBuffer()
//初始化文件数据缓冲区
{
	int i=0;
    t_32 BufferBase=BUFFER_BASE;
    FreeHead=&FileBuffer[0];//FreePoint指向第一个空闲块
    FileBuffer->PrevFree=&FileBuffer[NR_FILE_BUFFER-1];
    FileBuffer[0].NextFree=&FileBuffer[1];
    FileBuffer[0].DirtyLink=NULL;

    	FileBuffer[0].Count=0;
	    FileBuffer[0].Dirty=0;
		FileBuffer[0].Block=NO_BLOCK;
		FileBuffer[0].Device=NO_DEVICE;
    
	for(i=1;i<NR_FILE_BUFFER-1;i++)
	{	
		//初始化空闲链,全部FileBuffer都链入空闲块
		FileBuffer[i].NextFree=&FileBuffer[i+1];
        FileBuffer[i].PrevFree=&FileBuffer[i-1];
      
		FileBuffer[i].Count=0;
	    FileBuffer[i].Dirty=0;
		FileBuffer[i].Block=0;
		FileBuffer[i].Device=0;
      
		//哈希链
	    FileBuffer[i].Hash=NULL;
		//修改链
		FileBuffer[i].DirtyLink=NULL;
	}
	//最后一块
	FreeTail=&FileBuffer[NR_FILE_BUFFER-1];//FreeTail指向最后一个空闲块
	FileBuffer[i].NextFree=&FileBuffer[0];
    FileBuffer[i].PrevFree=&FileBuffer[i-1];

		FileBuffer[i].Count=0;
	    FileBuffer[i].Dirty=0;
		FileBuffer[i].Block=0;
		FileBuffer[i].Device=0;
    
    FileBuffer[i].Hash=NULL;
	FileBuffer[i].DirtyLink=NULL;
	
	for(i=0;i<NR_FILE_BUFFER;i++)
	{
		FileBuffer[i].Data=(t_8 *)BufferBase;
		BufferBase+=BUFFER_SIZE;
	}
	printk("Init Buffer");



}

PRIVATE HDRead(t_32 Begin,t_32 pBuffer,t_32 Block)
//读硬盘
//Begin开始的扇区号,pBuffer数据区指针,Block要读的块数
{
	//填写消息
/*	Message mMessage;
	mMessage.Type=READ;
	mMessage.SECTORS=Block*2;
	mMessage.FSADDR=(int)pBuffer;
	mMessage.STARTSECTOR=Begin*2; 
	mMessage.Next=NULL;	
    //发送消息
	SendMessage( HD,&mMessage);	
	ChangeProcess();
	WaitMessage(FS,HD,NULL);*/
	int i=0;
	char *Data=(char *)pBuffer;	
	for(i=0;i<Block;i++)
	{
		readSector(Begin+i,Data);
		Data+=512;
	}
	
}

PRIVATE HDWrite(t_32 Begin,t_32 pBuffer,t_32 Block)
//写硬盘
//Begin开始的扇区号,pBuffer数据区指针,Block要读的块数
{
	//填写消息
/*	Message mMessage;
	mMessage.Type=WRITE;
	mMessage.SECTORS=Block*2;
	mMessage.FSADDR=(int)pBuffer;
	mMessage.STARTSECTOR=Begin*2; 
	mMessage.Next=NULL;
	//发送消息
	SendMessage( HD,&mMessage);
	ChangeProcess();
	WaitMessage(FS,HD,NULL);*/
	int i=0;
	char *Data=(char *)pBuffer;	
	for(i=0;i<Block;i++)
	{
		writeSector(Begin+i,Data);
		Data+=512;
	}
//	printk("hui lai le\n");
}


PUBLIC LPBuffer GetFreeBlock()
//从文件数据缓冲区中取得空的可用的块
{
    LPBuffer p=NULL;
	if(FreeTail==NULL)
		//无可用空闲块
		return NULL;
    p=FreeTail;
	//指向前一块空闲块
    FreeTail=FreeTail->PrevFree;
	//返回空闲块
	return p;

}


PUBLIC void FreeBufferBlock(LPBuffer pFileBuffer)
//释放不用的文件数据缓冲区块
{

	 LPBuffer p=NULL;
	 //如果被修改过则链入修改链
	 if(pFileBuffer->Dirty==DIRTY)	
	 {	 // printk("%x\n",pFileBuffer->Data); 
		HDWrite(pFileBuffer->Block,(t_32)pFileBuffer->Data,1);//写盘 

		    /*pFileBuffer->DirtyLink=DirtyLink;
			DirtyLink=pFileBuffer;*/
	 }
     p=HashBuffer[MASK(pFileBuffer->Block)];//取得所在哈希链表的头指针
	 if(!p)
		 //不存在,出错
		 printk("HashBuffer No Exit,Error!\n");
	//找到pFileBuffer前一项
	 while(p&&p->Hash)
	 {
		 if(p->Hash->Block==pFileBuffer->Block&&
            p->Hash->Device==pFileBuffer->Device)
			break;
		 p=p->Hash;
	 }
	 p->Hash=pFileBuffer->Hash;//将pFileBuffer从Hash链中删除

	 //清空相关项
     pFileBuffer->Count=0;
	 pFileBuffer->Block=NO_BLOCK;
     pFileBuffer->Device=NO_DEVICE;
	 pFileBuffer->Dirty=CLEAR;

	 //pFileBuffer链入空闲链表,成为第一个空闲块
     pFileBuffer->NextFree=FreeHead;
	 FreeHead=pFileBuffer;


}


LPBuffer SearchBlock(int Block ,int Device)
//从哈希表中搜索指定的块
{   
    LPBuffer p=NULL;
	p=HashBuffer[MASK(Block)];//取得所在哈希链表的头指针

	//从哈希表中搜索
	 while(p)
	 {
		 if(p->Block==Block&&p->Device==Device)
			break;
		 p=p->Hash;
	 }

     //返回,没找到p将是NULL;
	 return p;





}

PRIVATE void DeHashLink(LPBuffer pFileBuffer)
//将指定块链入哈希表
{	
	LPBuffer p=NULL;
	p=HashBuffer[MASK(pFileBuffer->Block)];//取得所在哈希链表的头指针
	//该块成为该哈希链第一块
    if(!p)
	{
       HashBuffer[MASK(pFileBuffer->Block)]=pFileBuffer;
	   return ;
	}
	//移动到哈希表尾
	while(p->Hash)	
		 p=p->Hash;
	//链入表尾
     p->Hash=pFileBuffer;

	
}

//取得指定的物理块
PUBLIC LPBuffer GetPhysicalBlock(int Block ,int Device)
//先从哈希表中搜索没找到
//就从空闲块中取出一块
//并将相应块从设备读入,链入哈希表中
{
	LPBuffer p=NULL;
    p=SearchBlock(Block , Device);//从哈希表中搜索
	t_8 *Data;
	int i=0;
	//找到,返回
	if(p)
		return p; 
	p=FreeHead;
	//从空闲链中搜索
	while(p)
	{
		//提高刚使用文件缓冲时的搜索效率
		if(p->Device==NO_DEVICE&&p->Block==NO_BLOCK)
			break;

		if(p->Device==Device&&p->Block==Block)
			if(p->Dirty)
			{
				//被修改过,先写回磁盘  
				HDWrite(Block,(t_32)p->Data,1);

				//返回
				return p;

			}
	}
	
	//从空闲块中取出一块
	p=GetFreeBlock();
	if(!p)
		//无可用块了,出错
		printk("Out Of DataBuffer!\n");

    //IO读入相应的块
    HDRead(Block,(t_32)p->Data,1);
	//printk("Read hui lai le\n");
	Data=p->Data;

    p->Block=Block;
	p->Device=Device;
	p->Count++;


	//将相应块链入哈希表
      DeHashLink(p);
	  
	return p;



}
	
PUBLIC void Sysnc()
//将修改过的数据块,全部写入磁盘
{
	LPBuffer pDirty=DirtyLink;
    LPBuffer pPrevDirty;
	//
	while(pDirty)
	{
		if(pDirty->Dirty==DIRTY)
		   HDWrite(pDirty->Block,(t_32)pDirty->Data,1);//写盘
		pDirty->Dirty=CLEAR;
		pPrevDirty=pDirty;
		pDirty=pDirty->DirtyLink;
		pPrevDirty->DirtyLink=NULL;

	}
	DirtyLink=NULL;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -