rw.c

来自「参照MINIX3写的操作系统 用GCC+NASM+BOCHS开发」· C语言 代码 · 共 687 行 · 第 1/2 页

C
687
字号
#include "../kernel.h"
#include "FileSystem.h"

extern LPBuffer GetPhysicalBlock(int Block ,int Device);

extern void FreeBufferBlock(LPBuffer pFileBuffer);
t_32 GetAddressFromIndirectBlock(t_8 Device,t_32 Block,t_32 NumberInOneBlock)
//从间接块中读出NumberInOneBlock所对应的Address
{
	t_32 i;
    LPBuffer Buf;
	char *p;
	t_32 BlockAddress;
	
	if(NumberInOneBlock<0||NumberInOneBlock>=256)
		return ERROR;
	Buf=GetPhysicalBlock(Block,Device);
	p=Buf->Data;
	for(i=1;i<=NumberInOneBlock;i++)
		p+=4;
	BlockAddress=(*(t_32 *)p);
	return BlockAddress;
}

t_bool SetAddressToIndirectBlock(t_8 Device,t_32 Block,t_32 NumberInOneBlock,t_32 Address)
//将物理块写入Inode
{
	t_32 i;
    LPBuffer Buf;
	char *p;

	
	if(NumberInOneBlock<0||NumberInOneBlock>=256)
		return ERROR;
	Buf=GetPhysicalBlock(Block,Device);
	p=Buf->Data;
	Buf->Dirty=DIRTY;
	for(i=1;i<=NumberInOneBlock;i++)
		p+=4;
	(*(t_32 *)p)=Address;
	FreeBufferBlock(Buf);
	return OK;

}
t_32 FileBlockToPhysicalBlock(LPInode pInode,t_32 BlockNumber,t_8 Device)
{
	t_32 PhysicalBlock;
//	t_32 BlockNumber1;

	if(0<=BlockNumber&&BlockNumber<12)//直接块
	{
		//直接块对应的物理块,直接保存在Inode中
		PhysicalBlock=pInode->Block[BlockNumber];
		return	PhysicalBlock;
	}
	else if(12<=BlockNumber&&BlockNumber<(12+256))//一次间接块
	{
		//从一次间接块中读取BlockNumber对应的物理块号
		BlockNumber=BlockNumber-12;
		PhysicalBlock=GetAddressFromIndirectBlock(Device,pInode->Block[12],BlockNumber);
		return 	PhysicalBlock;
	}else
	{
		printk("暂时不支持\n");
		return -1;
	}
	/*else if(256<BlockNumber<=(12+256+256*256))//二次间接块
	{	
		BlockNumber1=(BlockNumber-12-256)/256;//计算二次间接块中,一次间接块的块号
		//取得一次间接块块号
		PhysicalBlock=ReadPhysicalBlock(Inode->Block[13],BlockNumber1);
		//计算BlockNumber在块内的位置
    	BlockNumber1=(BlockNumber-12-256)%256;
		PhysicalBlock=ReadPhysicalBlock(BlockAddress,BlockNumber1);
		return 	PhysicalBlock;
	}
	else if((12+256+256*256)<BlockNumber<=(12+256+256*256+256*256*256))//读三次间接块
	{	
		//计算三次间接块中,二次间接块的块号
		BlockNumber1=(BlockNumber-12-256-256*256)/256;
       	//取得二次间接块块号
		PhysicalBlock=ReadPhysicalBlock(Inode->Block[14],BlockNumber1);
        //计算三次间接块中,一次间接块的块号
		BlockNumber1=(BlockNumber-12-256-256*256)/(256*256);
       	//取得一次间接块块号
		PhysicalBlock=ReadPhysicalBlock(BlockAddress,BlockNumber1);
		//计算直接块在块内的位置
		BlockNumber1=(BlockNumber-12-256-256*256)%(256*256);
		//取得直接块
		PhysicalBlock=ReadPhysicalBlock(BlockAddress,BlockNumber1);
		return 	PhysicalBlock;
	}*/
}

short GetBit(int Start,char Byte)
//返回Byte从Start位起第一个Value值(0或1)所在的位置
{
	int i=0;
	/*if(Value==0)
		Byte=(~Byte);*/
	for(i=Start;i<8;i++)
	{
		if(((~Byte)>>i)&1)
			return i;
	}
	return -1;
}
void SetBit(unsigned char *Byte,int Bit)
{
unsigned char Temp=0x1;;
    
	switch(Bit)
	{
	case 0:Temp=0x1;break;
	case 1:Temp=0x2;break;
	case 2:Temp=0x4;break;
	case 3:Temp=0x8;break;
	case 4:Temp=0x10;break;
	case 5:Temp=0x20;break;
	case 6:Temp=0x40;break;
	case 7:Temp=0x80;break;
	default :break;

	}
	*Byte|=Temp;

}
t_32 SearachFreeBlock(t_8 Device,t_32 StartPosition,t_32 Count,t_8 Value)
//不包括StartPosition本身
//在从指定的位置开始在块位图中搜索Count个块返回第一个空闲块
{
	t_32 BitmapBlock=0;
	t_32 LocalStart=0;
	t_32 CurrentPosition=0;
	LPBuffer pBlock=NULL;
	t_32 i=0;
	short Temp;

	char *Byte;
	//根据StartPosition计算第一块位图块的位置给BitmapBlock
	BitmapBlock=StartPosition/(1024*8);
	CurrentPosition+=BitmapBlock*8192;
    pBlock=GetPhysicalBlock(BitmapBlock++,Device);//取得该块
	printk("pBlock %x\n",pBlock);
	//计算块内的开始位置
	LocalStart=StartPosition-CurrentPosition;
	CurrentPosition=(StartPosition-StartPosition%8);
	Byte=pBlock->Data; 
	Byte+=(LocalStart/8);
	if((Temp=GetBit(StartPosition-CurrentPosition,*Byte))!= -1)
	{
            SetBit((unsigned char *)Byte,Temp);
			pBlock->Dirty=DIRTY;
			FreeBufferBlock(pBlock);
			return (CurrentPosition+i*8+Temp);
	}
	i+=1;
	Byte++;	
	while(i<Count)
	{
		if((i+(LocalStart/8))>1023)
		{
			pBlock=GetPhysicalBlock(BitmapBlock++,Device);
			Byte=pBlock->Data;
			CurrentPosition+=i*8;
			i=0;
			Count-=(i*8);
		}

		if((Temp=GetBit(0,*Byte))!= -1)
		{
            SetBit((unsigned char *)Byte,Temp);
			pBlock->Dirty=DIRTY;	
			FreeBufferBlock(pBlock);
			return (CurrentPosition+i*8+Temp);
		}
		else
		{
			i+=1;
			Byte++;	
		}


	}
	return ERROR;

}

t_32 NewMallocPhysicalBlock(LPSuper Super,LPInode pInode,int EstimateSize)
//开辟新的物理块
{
  t_32 Block;
  //t_32 NextFreeBlock;
  Block=Super->FirstFreeBlock;//取得FirstFreeBlock所指的空闲块
  //如果预分配以超出磁盘空间范围,就不再进行预分配,直接用最近空闲块
  //if(Super->FirstFreeBlock+EstimateSize>HD_SIZE) 
  pInode->FutuerBlocks=EstimateSize;
  Super->FirstFreeBlock+=EstimateSize;
  //NextFreeBlock=SearachFreeBlock(Block+EstimateSize);//搜索下一个空闲块的位置
  //Super->FirstFreeBlock=NextFreeBlock;
  Block=SearachFreeBlock(0,Block,EstimateSize,0);
  return Block;

}
t_32 AllotInode(LPSuper Super)
{
	return SearachFreeBlock(0,Super->FirstFreeInode,Super->TotalInode,0);
}

t_32 OldMallocPhysicalBlock(LPSuper Super,LPInode pInode)
{	
	if(pInode->Blocks==0)
		return ERROR;
	if((pInode->Blocks%pInode->FutuerBlocks)==0)
	{
		return NewMallocPhysicalBlock(Super,pInode,pInode->FutuerBlocks);
        
	}
	else
	return SearachFreeBlock(0, pInode->LastBlock,10000,0);
}
/*PhysicalBlockToFileBlock0(LPSuper SuperBlock,LPInode pInode,t_32 PhysicalBlock,t_8 Device)
{
	pInode->Block[FileBlockSize]=PhysicalBlock;
}
PhysicalBlockToFileBlock1(LPInode pInode,t_32 IndirectBlock1,t_32 PhysicalBlock,t_8 Device)
{
	if(IndirectBlock1==0)//一次间接块指针尾空
		{
			//申请新块,作为一次间接块
			NewBlock=OldMallocPhysicalBlock(LPInode pInode);
            //取得该块
			pBuffer=GetPhysicalBlock(NewBlock ,Device);
			Data=pBuffer->Data;
			//清零
			memset((void *)Data,1024,0);
            //将PhysicalBlock写入一次块
			SetAddressToIndirectBlock(Device,NewBlock,0,PhysicalBlock);

		}
		else//一次块已经存在
		{  
			//计算新的PhysicalBlock在一次间接块中的位置
            NewBlock=FileBlockSize-12;
			//将PhysicalBlock写入一次块
			SetAddressToIndirectBlock(Device,IndirectBlock1,NewBlock,PhysicalBlock);

		}
}
PhysicalBlockToFileBlock2(LPInode pInode,t_32 IndirectBlock2,t_32 PhysicalBlock,t_8 Device)
{
	if(IndirectBlock2==0)//二次间接块指针为空
		{	
			//申请新块,作为二次间接块
			NewBlock2=OldMallocPhysicalBlock(LPInode pInode);
            //取得该块
			pBuffer=GetPhysicalBlock(NewBlock ,Device);
			Data=pBuffer->Data;
			//清零
			memset((void *)Data,1024,0);
           	//申请新块,作为一次间接块
			NewBlock1=OldMallocPhysicalBlock(LPInode pInode);
            //取得该块
			pBuffer=GetPhysicalBlock(NewBlock ,Device);
			Data=pBuffer->Data;
			//清零
			memset((void *)Data,1024,0);
            //将一次间接块写入二次块间接块
			SetAddressToIndirectBlock(Device,NewBlock2,0,NewBlock1)
			//将PhysicalBlock写入一次块
			SetAddressToIndirectBlock(Device,NewBlock1,0,NewBlock1)
		}
		else //二次间接块存在
		{
	    	if((FileBlockSize-12-256)/256==0)//一次间接块指针为空
			{  
				//申请新块,作为一次间接块
				NewBlock1=OldMallocPhysicalBlock(LPInode pInode);
				//取得该块
				pBuffer=GetPhysicalBlock(NewBlock ,Device);
				Data=pBuffer->Data;
				//清零
				memset((void *)Data,1024,0);
				//将一次间接块写入二次块间接块
				SetAddressToIndirectBlock(Device,Inode->Block[13],0,NewBlock1);

			}
			else//一次间接块存在
			{
				
				//计算一次块在二次块中的位置
				NewBlock1=(FileBlockSize-12-256)/256;
				NewBlock1=GetAddressFromIndirectBlock(Device,Inode->Block[13],NewBlock1);
				//计算新的PhysicalBlock在一次间接块中的位置
				NewBlock=(FileBlockSize-12-256)%256;
            	//将PhysicalBlock写入一次块
		    	SetAddressToIndirectBlock(Device,NewBlock1,NewBlock,PhysicalBlock);
				
			}
		}

	}

}*/
void PhysicalBlockToFileBlock(LPSuper Super,LPInode pInode,t_32 PhysicalBlock,t_8 Device)
{
	t_32 FileBlockSize=	pInode->FileSize/1024 ;//计算总的文件块数+1(新加进的块)
    t_32 NewBlock;
	LPBuffer pBuffer;
	char *Data;
	if(0<=FileBlockSize&&FileBlockSize<12)//在直接块内
        pInode->Block[FileBlockSize]=PhysicalBlock;
	else if(12<=FileBlockSize&&FileBlockSize<(12+256))//在一次间接块内
	{
	  
		if(pInode->Block[12]==0)//一次间接块指针尾空
		{
			//申请新块,作为一次间接块
			NewBlock=OldMallocPhysicalBlock(Super,pInode);
            //取得该块
			pBuffer=GetPhysicalBlock(NewBlock ,Device);
			Data=pBuffer->Data;
			//清零
			MemorySet((void *)Data,0,1024);
            //将PhysicalBlock写入一次块
			pInode->Block[12]=NewBlock;
			SetAddressToIndirectBlock(Device,NewBlock,0,PhysicalBlock);

		}
		else//一次块已经存在
		{  
			//计算新的PhysicalBlock在一次间接块中的位置
            NewBlock=FileBlockSize-12;
			//将PhysicalBlock写入一次块
			SetAddressToIndirectBlock(Device,pInode->Block[12],NewBlock,PhysicalBlock);

		}

	}else
	{
		printk("暂时不支持\n");
	}
	pInode->LastBlock=PhysicalBlock;
	/*pInode->Blocks+=1;

⌨️ 快捷键说明

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