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

📄 ul_inode.cpp

📁 类似Linux操作系统0.11版文件系统的文件系统设计和Windows下的操作程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			// 该i 节点。如果该i 节点的已修改标志和锁定标志均为0,则我们可以使用该i 节点,于是退出循环。
			if (!last_inode->i_count)
			{
				inode = last_inode;
				if (!inode->i_dirt && !inode->i_lock)
					break;
			}
		}
		// 如果没有找到空闲i 节点(inode=NULL),则将整个i 节点表打印出来供调试使用,并死机。
		if (!inode)
		{
			for (i = 0; i < NR_INODE; i++)
				printk ("%04x: %6d\t", inode_table[i].i_dev,
				inode_table[i].i_num);
			panic ("No free inodes in mem");
		}
		// 等待该i 节点解锁(如果又被上锁的话)。
		wait_on_inode (inode);
		// 如果该i 节点已修改标志被置位的话,则将该i 节点刷新,并等待该i 节点解锁。
		while (inode->i_dirt)
		{
			write_inode (inode);
			wait_on_inode (inode);
		}
	}
	while (inode->i_count);	// 如果i 节点又被其它占用的话,则重新寻找空闲i 节点。
	// 已找到空闲i 节点项。则将该i 节点项内容清零,并置引用标志为1,返回该i 节点指针。
	memset (inode, 0, sizeof (*inode));
	inode->i_count = 1;
	return inode;
}

//// 从设备上读取指定节点号的i 节点。
// nr - i 节点号。
struct m_inode *iget (int dev, int nr)
{
	struct m_inode *inode, *empty;

	if (!dev)
		panic ("iget with dev==0");
	// 从i 节点表中取一个空闲i 节点。
	empty = get_empty_inode ();
	// 扫描i 节点表。寻找指定节点号的i 节点。并递增该节点的引用次数。
	inode = inode_table;
	while (inode < NR_INODE + inode_table)
	{
		// 如果当前扫描的i 节点的设备号不等于指定的设备号或者节点号不等于指定的节点号,则继续扫描。
		if (inode->i_dev != dev || inode->i_num != nr)
		{
			inode++;
			continue;
		}
		// 找到指定设备号和节点号的i 节点,等待该节点解锁(如果已上锁的话)。
		wait_on_inode (inode);
		// 在等待该节点解锁的阶段,节点表可能会发生变化,所以再次判断,如果发生了变化,则再次重新
		// 扫描整个i 节点表。
		if (inode->i_dev != dev || inode->i_num != nr)
		{
			inode = inode_table;
			continue;
		}
		// 将该i 节点引用计数增1。
		inode->i_count++;
		if (inode->i_mount)
		{
			int i;

			// 如果该i 节点是其它文件系统的安装点,则在超级块表中搜寻安装在此i 节点的超级块。如果没有
			// 找到,则显示出错信息,并释放函数开始获取的空闲节点,返回该i 节点指针。
			for (i = 0; i < NR_SUPER; i++)
				if (super_block[i].s_imount == inode)
					break;
			if (i >= NR_SUPER)
			{
				printk ("Mounted inode hasn't got sb\n");
				if (empty)
					iput (empty);
				return inode;
			}
			// 将该i 节点写盘。从安装在此i 节点文件系统的超级块上取设备号,并令i 节点号为1。然后重新
			// 扫描整个i 节点表,取该被安装文件系统的根节点。
			iput (inode);
			dev = super_block[i].s_dev;
			nr = ROOT_INO;
			inode = inode_table;
			continue;
		}
		// 已经找到相应的i 节点,因此放弃临时申请的空闲节点,返回该找到的i 节点。
		if (empty)
			iput (empty);
		return inode;
	}
	// 如果在i 节点表中没有找到指定的i 节点,则利用前面申请的空闲i 节点在i 节点表中建立该节点。
	// 并从相应设备上读取该i 节点信息。返回该i 节点。
	if (!empty)
		return (NULL);
	inode = empty;
	inode->i_dev = dev;
	inode->i_num = nr;
	read_inode (inode);
	return inode;
}

//// 从设备上读取指定i 节点的信息到内存中(缓冲区中)。
static void read_inode (struct m_inode *inode)
{
	struct super_block *sb;
	struct buffer_head *bh;
	int block;

	// 首先锁定该i 节点,取该节点所在设备的超级块。
	lock_inode (inode);
	if (!(sb = get_super (inode->i_dev)))
		panic ("trying to read inode without dev");
	// 该i 节点所在的逻辑块号 = (启动块+超级块) + i 节点位图占用的块数 + 逻辑块位图占用的块数 +
	// (i 节点号-1)/每块含有的i 节点数。
	block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
		(inode->i_num - 1) / INODES_PER_BLOCK;
	// 从设备上读取该i 节点所在的逻辑块,并将该inode 指针指向对应i 节点信息。
	if (!(bh = bread (inode->i_dev, block)))
		panic ("unable to read i-node block");
	*(struct d_inode *) inode =
		((struct d_inode *) bh->b_data)[(inode->i_num - 1) % INODES_PER_BLOCK];
	// 最后释放读入的缓冲区,并解锁该i 节点。
	brelse (bh);
	unlock_inode (inode);
}

//// 将指定i 节点信息写入设备(写入缓冲区相应的缓冲块中,待缓冲区刷新时会写入盘中)。
static void write_inode (struct m_inode *inode)
{
	struct super_block *sb;
	struct buffer_head *bh;
	int block;

	// 首先锁定该i 节点,如果该i 节点没有被修改过或者该i 节点的设备号等于零,则解锁该i 节点,
	// 并退出。
	lock_inode (inode);
	if (!inode->i_dirt || !inode->i_dev)
	{
		unlock_inode (inode);
		return;
	}
	// 获取该i 节点的超级块。
	if (!(sb = get_super (inode->i_dev)))
		panic ("trying to write inode without device");
	// 该i 节点所在的逻辑块号 = (启动块+超级块) + i 节点位图占用的块数 + 逻辑块位图占用的块数 +
	// (i 节点号-1)/每块含有的i 节点数。
	block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
		(inode->i_num - 1) / INODES_PER_BLOCK;
	// 从设备上读取该i 节点所在的逻辑块。
	if (!(bh = bread (inode->i_dev, block)))
		panic ("unable to read i-node block");
	// 将该i 节点信息复制到逻辑块对应该i 节点的项中。
	((struct d_inode *) bh->b_data)
		[(inode->i_num - 1) % INODES_PER_BLOCK] = *(struct d_inode *) inode;
	// 置缓冲区已修改标志,而i 节点修改标志置零。然后释放该含有i 节点的缓冲区,并解锁该i 节点。
	bh->b_dirt = 1;
	inode->i_dirt = 0;
	brelse (bh);
	unlock_inode (inode);
}


//// 释放指定的i 节点。
// 复位对应i 节点位图比特位。
void free_inode (struct m_inode *inode)
{
	struct super_block *sb;
	struct buffer_head *bh;

	// 如果i 节点指针=NULL,则退出。
	if (!inode)
		return;
	// 如果i 节点上的设备号字段为0,说明该节点无用,则用0 清空对应i 节点所占内存区,并返回。
	if (!inode->i_dev)
	{
		memset (inode, 0, sizeof (*inode));
		return;
	}
	// 如果此i 节点还有其它程序引用,则不能释放,说明内核有问题,死机。
	if (inode->i_count > 1)
	{
		printk ("trying to free inode with count=%d\n", inode->i_count);
		panic ("free_inode");
	}
	// 如果文件目录项连接数不为0,则表示还有其它文件目录项在使用该节点,不应释放,而应该放回等。
	if (inode->i_nlinks)
		panic ("trying to free inode with links");
	// 取i 节点所在设备的超级块,测试设备是否存在。
	if (!(sb = get_super (inode->i_dev)))
		panic ("trying to free inode on nonexistent device");
	// 如果i 节点号=0 或大于该设备上i 节点总数,则出错(0 号i 节点保留没有使用)。
	if (inode->i_num < 1 || inode->i_num > sb->s_ninodes)
		panic ("trying to free inode 0 or nonexistant inode");
	// 如果该i 节点对应的节点位图不存在,则出错。
	if (!(bh = sb->s_imap[inode->i_num >> 13]))
		panic ("nonexistent imap in superblock");
	// 复位i 节点对应的节点位图中的比特位,如果该比特位已经等于0,则出错。
	if (clear_bit (inode->i_num & 8191, bh->b_data))
		printk ("free_inode: bit already cleared.\n\r");
	// 置i 节点位图所在缓冲区已修改标志,并清空该i 节点结构所占内存区。
	bh->b_dirt = 1;
	memset (inode, 0, sizeof (*inode));
}

//// 为设备dev 建立一个新i 节点。返回该新i 节点的指针。
// 在内存i 节点表中获取一个空闲i 节点表项,并从i 节点位图中找一个空闲i 节点。
struct m_inode *new_inode (int dev)
{
	struct m_inode *inode;
	struct super_block *sb;
	struct buffer_head *bh;
	int i, j;

	// 从内存i 节点表(inode_table)中获取一个空闲i 节点项(inode)。
	if (!(inode = get_empty_inode ()))
		return NULL;
	// 读取指定设备的超级块结构。
	if (!(sb = get_super (dev)))
		panic ("new_inode with unknown device");
	// 扫描i 节点位图,寻找首个0 比特位,寻找空闲节点,获取放置该i 节点的节点号。
	j = 8192;
	for (i = 0; i < 8; i++)
		if (bh = sb->s_imap[i])
			if ((j = find_first_zero (bh->b_data)) < 8192)
				break;
	// 如果全部扫描完还没找到,或者位图所在的缓冲块无效(bh=NULL)则 返回0,退出(没有空闲i 节点)。
	if (!bh || j >= 8192 || j + i * 8192 > sb->s_ninodes)
	{
		iput (inode);
		return NULL;
	}
	// 置位对应新i 节点的i 节点位图相应比特位,如果已经置位,则出错。
	if (set_bit (j, bh->b_data))
		panic ("new_inode: bit already set");

	// 置i 节点位图所在缓冲区已修改标志。
	bh->b_dirt = 1;
	// 初始化该i 节点结构。
	inode->i_count = 1;			// 引用计数。
	inode->i_nlinks = 1;		// 文件目录项链接数。
	inode->i_dev = dev;			// i 节点所在的设备号。
	inode->i_uid = 0;			// i 节点所属用户id。
	inode->i_gid = 0;			// 组id。
	inode->i_dirt = 1;			// 已修改标志置位。
	inode->i_num = j + i * 8192;	// 对应设备中的i 节点号。
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;	// 设置时间。
	return inode;				// 返回该i 节点指针。
}

⌨️ 快捷键说明

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