0.11版linux文件系统(二)

超级块描述了整个文件系统的信息,而文件作为存储的对象,它的信息是有inode节点来描述的。i节点位图描述了inode的使用情况。
struct m_inode{
            unsigned short i_mode; //文件类型
            unsigned short i_uid;//文件宿主
            unsigned long i_size;//文件大小
            unsigned long i_mtime;//文件修改时间
            unsigned char i_guid; //文件组id
            unsigned char i_nlinks;            //文件目录项连接数
            unsigned char i_zone[9];//文件所在的设备逻辑块号
//以下的字段在内存中
            struct task_struct *i_wait; //等待该i节点的进程
            unsigned long i_atime,i_ctime;
            unsigned short i_dev; //文件所在的设备号
            unsigned short i_num; //i节点号
            unsigned short i_count;//i节点被使用的次数,0表示空闲
            unsigned char i_lock;
            unsigned char i_dirt;
            unsigned char i_pipe;
            unsigned char i_mount; //该节点是否是某个文件系统的安装节点
            unsigned char i_seek;
            unsigned char i_update;
}
其 中i_zone[9]很重要,它指出了文件使用的设备的逻辑块号。其中0-6为直接块,也就是文件的数据直接在相应的逻辑块上;7位1级块,1级块可以包 含512个逻辑块号;8位2级块,它可以存放512个1级块。所以文件长度在7k以内只使用前7个位指定逻辑块,再大就要使用间接块指定了。
对i节点位图以及i节点的操作有new_inode,free_inode,iget,iput,bmp,以及namei.辅助的函数有get_empty_inode,read_inode,write_inode.内核维护了一个inode节点数组:
struct m_inode inode_table[NR_INODE]={{0,},};
new_inode(int dev)从inode_table中获取一个空闲的inode节点项,然后相应设备超级块中的i节点位图中的第一个0bit,接着设置inode节点信 息,并置引用为1。free_inode则相反,进行一系列测试后,它清除位图的相应比特为,并清空inode节点占用的内存。
对 逻辑块位图的操作有new_block和free_block,前者获取一个空闲缓冲块并置位相应比特位,后者相反。以上都是对内存中的inode数组以 及缓冲区中的位图进行操作,而最终要落实到设备特定的块上。read_inode是从设备上读取指定i节点的信息到内存中,write_inode是写入 指定i节点到设备。后者是将inode写到相应缓冲块中,并置位
b_dirt。这里涉及到计算指定的inode节点在设备上的逻辑块号:
//启动块+超级块+i节点位图块数+逻辑块位图块数+(i节点号-1)/每块含有的i节点
block=1+1+sb->s_imap_blocks+sb->s_zmap_blocks+(inode->s_inum)/INODES_PER_BLOCK;
iget 函数是从设备上读取指定的i节点。如同getblk,考虑到同步问题也是个反复的过程。它首先从i节点表中申请一个空闲i节点。然后搜索i节点表,看是否 有指定的i节点,如果没有就用read_inode从设备中读取到空闲节点就可返回。如果有则等待它解锁。等待过程中如果节点表发生变化那么要重新搜索。 若该i节点是某个文件系统的安装点,则读取相应文件系统的超级块并设置节点号为该文件系统的第一个inode,然后重新开始。
iput是回写到设 备,这里根据文件的类型有几种不同的处理方法。如果文件是管道文件,则唤醒管道上等待的进程,并释放管道页面。管道的物理内存地址在inode-> i_size字段。如果文件是块设备,那么刷新设备。inode->i_zone[0]中存放的是设备号。如果链接数为0,则释放i节点所有的逻辑 块,并释放该节点。
还有一个比较重要的函数是 _bmp,它是将文件数据块映射到盘块。在前面讲过的do_no_page中用到过,计算出缺页的内存地址在程序所占的块号后,通过bmp映射到设备上的块号,并读取被交换到块设备上的页面。
下面具体讲解一下:
//inode:文件的节点,block:文件中的块号;create:创建标志。
static int _bmp(struct m_inode *inode,int block,int create)
{
            struct buffer_head *bh;
            int i;
            if(block<0)
                        panic("_bmp:block<0");
//如果块号大于直接块数+间接块数+二次间接块数,则超出文件系统表示范围,死机
            if(block>=7+512+512*512)
                        panic("_bmp:block>big");
//如果块号小于7,则使用直接块表示
            if(block<7){
                        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];
            }
//否则就看是不是在间接块中
            block-=7;
            if(block<512){
//如果间接块没有创建且创建标志为1,那么创建间接块
                        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->_zone[7])
                                    return 0;
//读取设备上的一次间接块
                        if(!(bh=bread(inode->i_dev,inode->i_zone[7])))
                                    return 0;
//取间接块第block上的逻辑块号
                        i=((unsigned short*)(bh->b_data))[block];
                        if(create&&!i)
                                    if(i=new_block(inode->i_dev)){
                                    ((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;
            i=((unsigned short*)bh->b_data)[block>>9];
            if(create&&!i)
                        if(i=new_block(inode->i_dev){
                                    bh->b_dirt=1;
                        }
            brelse(bh);
            if(!i)
                        return 0;
//读取二次间接块的二级块
            if(!(bh=bread(inode->i_dev,i))
                        return 0;
//取二级块上的block项的逻辑号
            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;
}
bmp是create=0的_bmp,仅取文件中的数据块号在缓冲区的对应块号,而create_block则是create=1的_bmp,它创建对应的设备逻辑块的缓冲块。

到 目前为止,应该对超级块,i节点,逻辑块,缓冲块有了一定的认识了。设备上的物理部分都有内存的表示,比如超级块在内存中有超级块数组 super_block[NR_SUPER],i节点和逻辑块位图有s_imap[8]和s_zmap[8]指向的缓冲区表示,i节点在内存中有i节点数 组inode_table[NR_INODE],逻辑块有缓冲区中的缓冲块。分配inode和逻辑块只需要分配内存中保留的空闲块,并设置对应位图和修改 位,内核会在适当时间刷新到设备上。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
操作系统课程设计 【设计题目】 文件系统设计 【开发语言及实现平台或实验环境】 C++/VC++ 【设计目的】 (1)本实验的目的是通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能和内部实现。 (2)结合数据结构、程序设计、计算机原理等课程的知识,设计一个文件系统,进一步理解操作系统。 (3)通过分对实际问题的分析、设计、编程实现,提高学生实际应用、编程的能力 【设计要求】 理解级目录的文件系统的组织;掌握常用的数据结构;系统采用两级目录,其中第一级对应于用户账号,第级对应于用户帐号下的文件;使用文件来模拟外存,进行数据结构设计和操作算法的设计,实现一个文件系统并实现基本的文件操作(为了简便文件系统,不考虑文件共享,文件系统安全以及管道文件与设备文件等特殊内容)。要求: 1、 对程序的每一部分要有详细的设计分析说明 2、 程序执行的每个步骤要有具体的提示内容或输出 3、 源代码格式规范,注释不少于四分之一 4、 设计合适的测试用例,对得到的运行结果要有分析, 5、 设计中遇到的问题,设计的心得体会 6、 提交完整程序代码、课程设计报告及相关文档 【设计原理】 对采用级文件目录的文件系统工作的机理了如指掌,对文件系统的相关操作要掌握。 【设计内容】 一、 任务 为Linux系统设计一个简单的文件系统。要求做到以下几点: 1.可以实现下列几条命令: login 用户登录 dir 列目录 create 创建文件 delete 删除文件 open 打开文件 close 关闭文件 read 读文件 write 写文件 cd 进出目录 2.列目录时要列出文件名,物理地址,保护码和文件长度 3.源文件可以进行读写保护 、 程序设计 1. 设计思想 本文件系统采用两级目录,其中第一级对应于用户账号,第级对应于用户帐号下的文件。另外,为了简便文件系统未考虑文件共享,文件系统安全以及管道文件与设备文件等特殊内容。 首先应确定文件系统的数据结构:主目录、子目录及活动文件等。主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。 用户创建的文件,可以编号存储于磁盘上。如:file0,file1,file2…并以编号作为物理地址,在目录中进行登记。 2. 主要数据结构和部分代码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值