📄 ul_inode.cpp
字号:
#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 + -