Linux内核源码分析--文件系统(五、Inode.c)

来源:互联网 发布:网络热销产品 编辑:程序博客网 时间:2024/06/05 17:20


_bmap()

        1、_bmap()函数用于把一个文件数据块映射到盘块的处理操作

        

        因为一个i节点对应一个文件,所以上面的i节点映射的逻辑块号就是文件数据存放的逻辑块号;i_zone[0]到i_zone[6]是直接逻辑块号,i_zone[7]是一次间接逻辑块号,i_zone[8]是二次间接逻辑块号;文件中的数据存放在哪个硬盘上的逻辑块上就是由这个数组来映射的,根据这个也可以知道一个文件的最大存储是多少?

//把文件上的数据块映射到磁盘上,inode 文件i节点;block 文件中数据块号,create是否创建标志static int _bmap(struct m_inode * inode,int block,int create){struct buffer_head * bh;int i;//判断文件数据块号block是否超出范围if (block<0)panic("_bmap: block<0");if (block >= 7+512+512*512)//文件逻辑块的范围panic("_bmap: block>big");//使用直接块if (block<7) {if (create && !inode->i_zone[block])//创建标志置位,i节点对应的逻辑块字段为0if (inode->i_zone[block]=new_block(inode->i_dev)) {//申请一个新磁盘逻辑块,返回逻辑号inode->i_ctime=CURRENT_TIME;inode->i_dirt=1;}return inode->i_zone[block];//返回设备上的逻辑块号}//使用一次间接块block -= 7;if (block<512) {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;}if (!inode->i_zone[7])//表示创建间接块磁盘失败,或者create未置1return 0;if (!(bh = bread(inode->i_dev,inode->i_zone[7])))//读取间接块的信息return 0;i = ((unsigned short *) (bh->b_data))[block];//得到间接块上block所处的位置,判断是否为0if (create && !i)//如果间接块号上的block位置为0,create置位if (i=new_block(inode->i_dev)) {//申请一个新的逻辑块给block((unsigned short *) (bh->b_data))[block]=i;bh->b_dirt=1;}brelse(bh);return i;}//使用二次间接块block -= 512;//为二次间接块申请逻辑块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;}if (!inode->i_zone[8])return 0;//读取二级间接块信息if (!(bh=bread(inode->i_dev,inode->i_zone[8])))return 0;//获取block二级间接块号在指定的哪个二级间接块的一级块号i = ((unsigned short *)bh->b_data)[block>>9];//右移9位表示整除512,得到一级块号if (create && !i)//如果二级间接块中二级块不存在,则要为该二级块申请一个逻辑块号if (i=new_block(inode->i_dev)) {//得到一个逻辑块用来存放二级间接块中的二级间接块号((unsigned short *) (bh->b_data))[block>>9]=i;//block>>9 === block/512 为二级块映射一个逻辑块bh->b_dirt=1;}brelse(bh);if (!i)return 0;if (!(bh=bread(inode->i_dev,i)))//读取二级间接块中的二级块映射的缓存块return 0;i = ((unsigned short *)bh->b_data)[block&511];//表示在二级间接块中的二级块中的第几个数组元素if (create && !i)if (i=new_block(inode->i_dev)) {//申请一个逻辑块来存放最终的数据((unsigned short *) (bh->b_data))[block&511]=i;//映射下文件中的二级块bh->b_dirt=1;}brelse(bh);return i;//返回逻辑块号}

input()

        2、iput()函数是把i节点的引用递减,如果i节点引用为1,则递减删除i节点,并且设置相关属性;如果是管道文件或者块设备文件,则另外进行处理;

//放置一个i节点,减去1个i节点的引用void iput(struct m_inode * inode){if (!inode)return;wait_on_inode(inode);if (!inode->i_count)//如果i节点已经是0,那么死机panic("iput: trying to free free inode");if (inode->i_pipe) {//如果是管道文件wake_up(&inode->i_wait);//唤醒等待该管道的进程if (--inode->i_count)//引用减去1return;//如果还被其他程序引用,则直接返回;否则就设置一些属性和释放内存free_page(inode->i_size);//释放管道使用的内存页面inode->i_count=0;//对i节点属性字段设置inode->i_dirt=0;inode->i_pipe=0;return;}//i节点对应的设备号为0,引用递减后返回;如,管道操作i节点if (!inode->i_dev) {inode->i_count--;return;}//如果是块设备文件的i节点,刷新该设备if (S_ISBLK(inode->i_mode)) {sync_dev(inode->i_zone[0]);//zone[0]是设备号wait_on_inode(inode);}repeat:if (inode->i_count>1) {//引用递减  返回inode->i_count--;return;}if (!inode->i_nlinks) {//链接数为0, 表示文件已经删除,置文件长度为0,释放i节点truncate(inode);free_inode(inode);return;}if (inode->i_dirt) {//已经更改过write_inode(inode);/* we can sleep - so do again *///把i节点信息写入缓存中wait_on_inode(inode);goto repeat;//经过睡眠,要再一次确认}inode->i_count--;//递减返回,文件还存在return;}

get_empty_inode()

        3、get_empty_inode(void)函数 表示在i节点数组中查找一个空闲的i节点,进行设置,然后返回该i节点;

//从i节点表中获取一个空闲i节点项struct m_inode * get_empty_inode(void){struct m_inode * inode;static struct m_inode * last_inode = inode_table;int i;do {inode = NULL;for (i = NR_INODE; i ; i--) {if (++last_inode >= inode_table + NR_INODE)//如果last_inode已经到了最后一项,则重新扫描last_inode = inode_table;if (!last_inode->i_count) {//引用为0,inode = last_inode;if (!inode->i_dirt && !inode->i_lock)//没有修改,没有上锁,就选择这个i节点break;}}//没有找到i节点,打印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");}//检查下是否又被上锁wait_on_inode(inode);//若i节点信息修改过,则刷新等待i节点解锁while (inode->i_dirt) {write_inode(inode);wait_on_inode(inode);}} while (inode->i_count);//如果i节点又被别的进程使用,那么再找一个i节点//对空闲i节点详内容清零,设置引用,返回i节点指针memset(inode,0,sizeof(*inode));inode->i_count = 1;return inode;}

iget()

        4、iget(int dev, int nr)函数 根据设备号和i节点号得到i节点信息;其中有个重点判断的是该i节点是否是某个文件系统的安装节点。如果是,则把i节点释放一个引用;并且重新在该文件系统中查找i节点(也就是根节点)

//从设备上读取指定i节点号的i节点信息//参数 dev设备号,nr  i节点号//1、在内存中的i节点列表中扫描,若查找到了,则返回i节点指针//2、如果上面没有找到,则从设备上读取指定i节点号的i节点信息放入内存i节点表中,返回i节点指针struct m_inode * iget(int dev,int nr){struct m_inode * inode, * empty;if (!dev)panic("iget with dev==0");empty = get_empty_inode();//得到一个空闲i节点inode = inode_table;//i节点列表数组while (inode < NR_INODE+inode_table) {if (inode->i_dev != dev || inode->i_num != nr) {//设备号或者i节点号不相等,则看下一个inode++;continue;}//解锁,然后再确认下设备号和i节点号是否改变了wait_on_inode(inode);if (inode->i_dev != dev || inode->i_num != nr) {inode = inode_table;continue;}inode->i_count++;//引用//如果找到的i节点是其他文件系统的安装节点if (inode->i_mount) {int i;for (i = 0 ; i<NR_SUPER ; i++)if (super_block[i].s_imount==inode)//看看是哪个文件系统的安装节点break;//如果没有找到安装在此i节点上的超级块,则释放申请的空闲i节点if (i >= NR_SUPER) {printk("Mounted inode hasn't got sb\n");if (empty)iput(empty);//释放空闲i节点return inode;}//找到i节点安装的超级块,获取到该文件系统的设备号,得到nr为根节点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节点,则自己新建一个if (!empty)return (NULL);inode=empty;inode->i_dev = dev;inode->i_num = nr;read_inode(inode);//从设备上读取该i节点return inode;}

read_inode()

        5、读取设备上指定i节点的信息到缓存中,其中要分清楚,参数中的i节点是内存中使用的i节点,而程序后面是读取到硬盘上的i节点;这应该是从硬盘上的i节点中加载其信息到内存中的i节点处,也就是更新i节点信息;所以用读i节点信息(把i节点信息从硬盘上读取到缓存区中,从硬盘使用的i节点更新到内存使用的i节点)

//从设备上读取指定i节点的信息到缓存中static void read_inode(struct m_inode * inode){struct super_block * sb;struct buffer_head * bh;int block;lock_inode(inode);if (!(sb=get_super(inode->i_dev)))//根据设备号获取到超级块panic("trying to read inode without dev");//下面是计算i节点逻辑号,引导块 超级块  两个位图 然后就是(i节点号/每块所拥有的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");*(struct d_inode *)inode =((struct d_inode *)bh->b_data)[(inode->i_num-1)%INODES_PER_BLOCK];//这是从硬盘中i节点上获取到数据,更新内存中i节点内容brelse(bh);unlock_inode(inode);}

write_inode()

        6、将指定i节点信息写入磁盘中,和上面的read_inode()函数正好相反,该函数是由内存中使用的i节点写入到硬盘上使用的i节点;把内存中修改过的i节点信息更新到硬盘上使用的i节点信息;

//将i节点信息写入缓存区中static void write_inode(struct m_inode * inode)//参数是内存中使用的i节点结构{struct super_block * sb;struct buffer_head * bh;int block;lock_inode(inode);if (!inode->i_dirt || !inode->i_dev) {unlock_inode(inode);return;}if (!(sb=get_super(inode->i_dev)))panic("trying to write inode without device");block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +(inode->i_num-1)/INODES_PER_BLOCK;//根据i节点号,找到磁盘逻辑块上i节点位置if (!(bh=bread(inode->i_dev,block)))//把该i节点磁盘块读取到缓存区panic("unable to read i-node block");((struct d_inode *)bh->b_data)//把该缓存区强转为 磁盘使用的i节点结构[(inode->i_num-1)%INODES_PER_BLOCK] =//根据i节点号,取余得到在该块磁盘上第几个位置为i节点*(struct d_inode *)inode;//由内存i节点强转为磁盘i节点结构,因为磁盘i节点结构和内存i节点结构前几位一样bh->b_dirt=1;inode->i_dirt=0;brelse(bh);unlock_inode(inode);}
         其实上面的读写i节点信息,只是在后面的转换顺序不一样。是在d_inode和m_inode结构体之间做文章的,因为两个结构体中前7项是一样的,也就是说前面7项是可以共用,可以改变的,而m_inode结构体中后面几项d_inode结构体中是没有的(其实这也是确定i节点的唯一性),所以也就不存在是否同步,是否一样。

        读i节点顺序是:*(struct d_inode *)inode = ((struct d_inode *)bh->b_data)[(inode->i_num-1)%INODES_PER_BLOCK];从硬盘映射的缓存区中读取到i节点信息到内存i节点结构体中;

        写i节点顺序是:((struct d_inode *)bh->b_data)[(inode->i_num-1)%INODES_PER_BLOCK] =*(struct d_inode *)inode;把i节点结构体内容从内存中写入到硬盘映射的缓存区中使用的i节点结构体(其实也就是硬盘上使用的i节点);

        转载请注明作者和原文出处,原文地址:http://blog.csdn.net/yuzhihui_no1/article/details/43951153

        若有不正确之处,望大家指正,共同学习!谢谢!!


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 不想考科目三了怎么办 科目三两次没过怎么办 练科目三很紧张怎么办 驾照学员卡丢了怎么办 驾考时考试的车系统出错怎么办 驾驶证超期6个月怎么办 北京汽车年检只有电子保单怎么办 交电费户号9位数怎么办 扬州驾照12分扣完了怎么办 有大专毕业证在深圳怎么办居住证 微信解释包错误怎么办 富士康离职不批怎么办 到了怀孕年龄找不到工作怎么办 建筑公司挂靠发生人员伤残怎么办 外地生小孩落北京户口怎么办 户籍档案查不到直系亲属关系怎么办 考过了二建注册怎么办 异地工作辞职回家档案怎么办 离职怎么办档案放在人才市场 人才房住了6年后怎么办 医保辞职后断了怎么办 社保断了生育险怎么办 深圳小产权房水电费纠纷怎么办 有公租房的再婚怎么办 廉租房被没收了怎么办 商铺到期房东不续租怎么办 天津集体户口买不起房怎么办 房东不想续租了怎么办 唯一住房卖掉后户口怎么办 杭州唯一住房卖掉后户口怎么办 唯一一套住房卖掉户口怎么办 房租押金条丢了怎么办 二建证书跟毕业证丢失怎么办 住宅房到70年怎么办 护照号变了机票怎么办 苹果se指纹坏了怎么办 月经推迟怎么办才能快点来 车载支架不粘了怎么办 otpc平板电脑无法开机怎么办 手表表轴掉了怎么办 鸡肉放冰箱臭了怎么办