inode与文件、目录 _VMware, Unix及操作系统讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  VMware, Unix及操作系统讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2009 | 回复: 0   主题: inode与文件、目录         下一篇 
zlasdf
注册用户
等级:新兵
经验:72
发帖:70
精华:0
注册:2011-10-17
状态:离线
发送短消息息给zlasdf 加好友    发送短消息息给zlasdf 发消息
发表于: IP:您无权察看 2015-7-3 11:40:05 | [全部帖] [楼主帖] 楼主

在inode里存放了文件数据所在磁盘数据块号,文件越大,所需要的块号就越多,这是因为文件在磁盘上的存放是不连续的。那为什么不用连续存放?这样只需要一个起始块号以及文件大小就可以描述整个文件的数据位置了。这回带来一些问题,包括很难增长文件大小,以及很容易产生磁盘碎片。

 

因此,还是采用存储每个块号的方式来存放文件数据在磁盘上的索引。当然,要想允许大文件且保持inode足够小,可以采用分级机制。在inode中有13个整数用来存放块号。前10个数是直接指向文件数据的块号,第11个数单级间接指向文件数据,即在第11个块号所指向的的数据块存放的是一个块号表。第12个数双级间接指向文件数据,即第12个块号指向一个单级间接块号表。第13个块号指向的是一个指向双级间接块号表。如下图所示:

--------

|direct|----->data block

--------

 

----------

|single  |--->----------

|indirect|    |direct 0|--->data block

----------    |direct 1|--->data block

              |...     |    ...

              |direct n|--->data block

              ----------

 

----------

|double  |--->-----------------

|indirect|    |single direct 0|--->...

----------    |single direct 1|--->...

              |...            |    ...

              |single direct n|--->...

              -----------------

……

 

这种方式能够存放多少数据呢?计算一下。假设一个磁盘块能存放1K字节,一个块号占用4个字节,那么:

10 direct blocks: 10 * 1K = 10K

1 indirect block with 256 direct blocks: 256 * 1K = 256K

1 double indirect block with 256 indirect blocks: 256 * 256K = 64M

1 triple indirect block with 256 double indirect blocks: 256 * 64M = 16G。

 

然而一个4字节整数能寻址的最大空间为4G,因此inode的这种块号组织方式足够用了,除非使用的是64位系统。

 

进程通过字节偏移量来访问文件中的数据,那么就需要将偏移量转换成磁盘块号。这里需要考虑分级层次,因此在实现起来会有一定的麻烦。内核提供bmap()函数来将偏移量转换成磁盘块号。处理如下:

struct Location

{

    BlockNo blkNo;

    ByteOffset off;

    Bytes nIO;

    BlockNo readAheadNo;

};

 

Location * bmap(INode * anINode, ByteOffset off)

{

    根据偏移量计算逻辑块号;

    计算块中的起始字节;

    计算要拷贝给用户的字节数;

    检查是否要预读,标记inode;

    确定间接索引的等级;

    while (不是在一个需要的等级)

    {

        根据逻辑块号来计算inode或间接块的索引;

        获取磁盘块号;

        brelse(未释放的磁盘块);

        若没有更多的间接索引等级则返回块号;

        读取间接索引磁盘块;

        根据间接索引的等级调整逻辑块号;

    }

}



 

将路径名映射到inode

目录与普通文件类似,只不过目录中数据存放的是目录项,该项包含的是inode号以及在该目录中的一个文件名(可以是目录)。路径名是一个以“/”分割的字符串。每个被“/”分开的部分称为一个组件。在UNIX system V中,组件最长为14个字节。

 

那么,如何将路径名映射到inode呢?每个进程都有一个u area,存放一个指向当前目录的指针。另外有一个全局变量存放根目录的inode。有了两个inode,映射就很简单了。

 

若一个进程要打开“/etc/passwd”文件,内核解析该路径名时,发现“/”,这样就将根目录作为工作目录,然后从该目录中(inode所包好的数据块中)查找etc,找到了匹配后得到了etc的inode号,然后读取etc的内容,在其中查找passwd,找到之后就可以返回对应的inode。处理过程如下:

INode * namei(String pathName) // 返回的是锁住的inode

{

    INode * cwINode = NULL;

    if (pathName[0] == '/')

        cwINode = iget(rootINodeNO);

    else

        cwINode = iget(currentDirINode);

 

    while (pathName中还有组件)

    {

        从pathName中读取下一个组件component;

        ISDIR(component) && 进程对该inode有对应的权限(否则返回权限错误);

        if (*cwINode is root INode && component == "..")

            continue;

        while (cwINode的数据还没有结束)

        {

            bmap()得到数据块号; bread()读取数据块;

            if (在cwINode的数据中找到component)

            {

                从该项中读取inode号matchINodeNo;

                iput(cwINode);

                cwINode = iget(matchINodeNo);

                brelse()释放数据块;

                break;

            }

            else

            {

                brelse()释放数据块;

                return (no inode);

            }

        }

    }

    return (cwINode);

}

 



--转自 北京联动北方科技有限公司




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论