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

📄 ul_inode.cpp

📁 类似Linux操作系统0.11版文件系统的文件系统设计和Windows下的操作程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "UL_FileSys.h"
#include "UL_Buffer.h"
#include "UL_Inode.h"
#include "UL_Block.h"
#include "UL_Super.h"

struct m_inode inode_table[NR_INODE];	// 定义i 节点表数组(32 项)

static void read_inode (struct m_inode *inode);
static void write_inode (struct m_inode *inode);

//// 等待指定的i 节点可用。
static inline void wait_on_inode (struct m_inode *inode)
{
}

//// 对指定的i 节点上锁(锁定指定的i 节点)
static inline void lock_inode (struct m_inode *inode)
{
	inode->i_lock = 1;
}

//// 对指定的i 节点解锁。
static inline void unlock_inode (struct m_inode *inode)
{
	inode->i_lock = 0;
}

//// 同步所有i 节点。
// 同步内存与设备上的所有i 节点信息。
void sync_inodes (void)
{
	int i;
	struct m_inode *inode;

	inode = 0 + inode_table;

	// 扫描i 节点表指针数组
	for (i = 0; i < NR_INODE; i++, inode++)
	{				
		wait_on_inode (inode);
		// 如果该i 节点已修改且不是管道节点,
		if (inode->i_dirt && !inode->i_pipe)
			write_inode (inode);
	}
}

//// 文件数据块映射到盘块的处理操作。(block 位图处理函数,bmap - block map)
// 参数:inode – 文件的i 节点;block – 文件中的数据块号;create - 创建标志。
// 如果创建标志置位,则在对应逻辑块不存在时就申请新磁盘块。
// 返回block 数据块对应在设备上的逻辑块号(盘块号)。
static int _bmap (struct m_inode *inode, int block, int create)
{
	struct buffer_head *bh;
	int i;

	if (block < 0)
		panic ("_bmap: block<0");

	if (block >= 7 + 512 + 512 * 512)
		panic ("_bmap: block>big");

	// 如果该块号小于7,则使用直接块表示。
	if (block < 7)
	{
		// 如果创建标志置位,并且i 节点中对应该块的逻辑块(区段)字段为0,则向相应设备申请一磁盘
		// 块(逻辑块,区块),并将盘上逻辑块号(盘块号)填入逻辑块字段中。然后设置i 节点修改时间,
		// 置i 节点已修改标志。最后返回逻辑块号。
		if (create && !inode->i_zone[block])
			if (inode->i_zone[block] = new_block (inode->i_dev))
			{
				inode->i_ctime = CURRENT_TIME;
				inode->i_dirt = 1;
			}
			return inode->i_zone[block];
	}

	// 如果该块号>=7,并且小于7+512,则说明是一次间接块。下面对一次间接块进行处理。
	block -= 7;
	if (block < 512)
	{
		// 如果是创建,并且该i 节点中对应间接块字段为0,表明文件是首次使用间接块,则需申请
		// 一磁盘块用于存放间接块信息,并将此实际磁盘块号填入间接块字段中。然后设置i 节点
		// 已修改标志和修改时间。
		if (create && !inode->i_zone[7])
		{
			if (inode->i_zone[7] = new_block (inode->i_dev))
			{
				inode->i_dirt = 1;
				inode->i_ctime = CURRENT_TIME;
			}
		}

		// 若此时i 节点间接块字段中为0,表明申请磁盘块失败,返回0 退出。
		if (!inode->i_zone[7])
			return 0;

		// 读取设备上的一次间接块。
		if (!(bh = bread (inode->i_dev, inode->i_zone[7])))
			return 0;

		// 取该间接块上第block 项中的逻辑块号(盘块号)。
		i = ((unsigned short *) (bh->b_data))[block];

		// 如果是创建并且间接块的第block 项中的逻辑块号为0 的话,则申请一磁盘块(逻辑块),并让
		// 间接块中的第block 项等于该新逻辑块块号。然后置位间接块的已修改标志。
		if (create && !i)
		{
			if (i = new_block (inode->i_dev))
			{
				((unsigned short *) (bh->b_data))[block] = i;
				bh->b_dirt = 1;
			}
		}
		// 最后释放该间接块,返回磁盘上新申请的对应block 的逻辑块的块号。
		brelse (bh);
		if (!i)
			return 0;
		return i;
	}

	// 程序运行到此,表明数据块是二次间接块,处理过程与一次间接块类似。下面是对二次间接块的处理。
	// 将block 再减去间接块所容纳的块数(512)。
	block -= 512;
	// 如果是新创建并且i 节点的二次间接块字段为0,则需申请一磁盘块用于存放二次间接块的一级块
	// 信息,并将此实际磁盘块号填入二次间接块字段中。之后,置i 节点已修改编制和修改时间。
	if (create && !inode->i_zone[8])
	{
		if (inode->i_zone[8] = new_block (inode->i_dev))
		{
			inode->i_dirt = 1;
			inode->i_ctime = CURRENT_TIME;
		}
	}
	// 若此时i 节点二次间接块字段为0,表明申请磁盘块失败,返回0 退出。
	if (!inode->i_zone[8])
		return 0;
	// 读取该二次间接块的一级块。
	if (!(bh = bread (inode->i_dev, inode->i_zone[8])))
		return 0;
	// 取该二次间接块的一级块上第(block/512)项中的逻辑块号。
	i = ((unsigned short *) bh->b_data)[block >> 9];
	// 如果是创建并且二次间接块的一级块上第(block/512)项中的逻辑块号为0 的话,则需申请一磁盘
	// 块(逻辑块)作为二次间接块的二级块,并让二次间接块的一级块中第(block/512)项等于该二级
	// 块的块号。然后置位二次间接块的一级块已修改标志。并释放二次间接块的一级块。
	if (create && !i)
	{	
		if (i = new_block (inode->i_dev))
		{
			((unsigned short *) (bh->b_data))[block >> 9] = i;
			bh->b_dirt = 1;
		}
	}
	brelse (bh);
	// 如果二次间接块的二级块块号为0,表示申请磁盘块失败,返回0 退出。
	if (!i)
		return 0;
	// 读取二次间接块的二级块。
	if (!(bh = bread (inode->i_dev, i)))
		return 0;
	// 取该二级块上第block 项中的逻辑块号。(与上511 是为了限定block 值不超过511)
	i = ((unsigned short *) bh->b_data)[block & 511];
	// 如果是创建并且二级块的第block 项中的逻辑块号为0 的话,则申请一磁盘块(逻辑块),作为
	// 最终存放数据信息的块。并让二级块中的第block 项等于该新逻辑块块号(i)。然后置位二级块的
	// 已修改标志。
	if (create && !i)
	{	
		if (i = new_block (inode->i_dev))
		{
			((unsigned short *) (bh->b_data))[block & 511] = i;
			bh->b_dirt = 1;
		}
	}
	// 最后释放该二次间接块的二级块,返回磁盘上新申请的对应block 的逻辑块的块号。
	brelse (bh);
	return i;
}

//// 根据i 节点信息取文件数据块block 在设备上对应的逻辑块号。
int bmap (struct m_inode *inode, int block)
{
	return _bmap (inode, block, 0);
}

//// 创建文件数据块block 在设备上对应的逻辑块,并返回设备上对应的逻辑块号。
int create_block (struct m_inode *inode, int block)
{
	return _bmap (inode, block, 1);
}

//// 释放一个i 节点(回写入设备)。
void iput (struct m_inode *inode)
{
	if (!inode)
		return;
	wait_on_inode (inode);	// 等待inode 节点解锁(如果已上锁的话)。
	if (!inode->i_count)
		panic ("iput: trying to free free inode");

	// 如果i 节点对应的设备号=0,则将此节点的引用计数递减1,返回。
	if (!inode->i_dev)
	{
		inode->i_count--;
		return;
	}

repeat:
	// 如果i 节点的引用计数大于1,则递减1。
	if (inode->i_count > 1)
	{
		inode->i_count--;
		return;
	}
	// 如果i 节点的链接数为0,则释放该i 节点的所有逻辑块,并释放该i 节点。
	if (!inode->i_nlinks)
	{
		truncate (inode);
		free_inode (inode);
		return;
	}
	// 如果该i 节点已作过修改,则更新该i 节点,并等待该i 节点解锁。
	if (inode->i_dirt)
	{
		write_inode (inode);	/* we can sleep - so do again */
		wait_on_inode (inode);
		goto repeat;
	}
	// i 节点引用计数递减1。
	inode->i_count--;
	return;
}

//// 从i 节点表(inode_table)中获取一个空闲i 节点项。
// 寻找引用计数count 为0 的i 节点,并将其写盘后清零,返回其指针。
struct m_inode *get_empty_inode (void)
{
	struct m_inode *inode;
	static struct m_inode *last_inode = inode_table;	// last_inode 指向i 节点表第一项。
	int i;

	do
	{
		// 扫描i 节点表。
		inode = NULL;
		for (i = NR_INODE; i; i--)
		{
			// 如果last_inode 已经指向i 节点表的最后1 项之后,则让其重新指向i 节点表开始处。
			if (++last_inode >= inode_table + NR_INODE)
				last_inode = inode_table;
			// 如果last_inode 所指向的i 节点的计数值为0,则说明可能找到空闲i 节点项。让inode 指向

⌨️ 快捷键说明

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