(莱昂氏unix源代码分析导读-41)文件系统树状结构的形成

                                                        

                             By cszhao1980


我们现在对inode有了一定的了解,正如前面所说,inode记录的信息比较靠近文件的物

理存储。那末,文件系统的树状结构是如何实现的呢?

 

答案就是“目录”。首先需要强调的是,目录也是一种文件,它也拥有与普通文件相同

inode结构。所不同的是其文件内容——逻辑上,我们可以把目录文件的内容看作一个

“目录项数组”,它由若干“目录项”构成,一个目录项对应于该目录内的一个文件,

16words(显然,1个块可容纳32个目录项),包含11 6位“i n o d e”表指针,以及

一个1 4个字符组成的名字。显然,inode指针即指向该文件的inode,而名字即该文件(或

目录)的名字。如果您对unix比较熟悉的话,您会知道,一个目录中比如含有的两个目录项:

当前目录(“.”)和父目录(“..”)。通过这种方式,目录就形成了文件系统树的一个结点,

从而形成了文件系统的树状结构。

 

而目录的inode结构中的i_size1记录的就是其文件总长度,即目录项总长度,而目录项的

个数 = i_size1/16

 

显然,当新建一个文件时,需要在其父目录的目录项中添加一项;而删除文件时,需要从

其父目录的目录项里将该文件的目录项删除——删除时,只需将inode指针置0即可(这些

目录项被称为空目录项,可以用于分配)。

 

namei(func, flag)用来搜索目录,返回执行文件的inode指针,它有两个参数:

1.        func:一个函数指针,每次调用该函数都将得到一个char,通过多次调用可获得一个字符串,而

该字符串为一个“路径名”;

    

2.        flag:搜索目的

10:“搜索”;

21:请求在父目录项中添加该文件的目录项;

32:请求在父目录中删除该文件的目录项。

 

对不同的搜索目的,namei的处理也有不同,比如,对一般的搜索目的,用户只需要对路径中每

个节点目录拥有“EXEC”权限,而“添加”、“删除”目的,则还需要在父目录中拥有“WRITE”权限。

 

namei的实现透露了很多有趣的信息:

1.        进程的u结构里定义了很多相关的结构,如:

(1)         u_cdir——指向“当前目录”的inode结构;

(2)         u_dbuf[DIRSIZ]——用来暂存读到的文件(目录)名;

(3)         u_offset[0~1]——记录当前读到的文件位置(偏移),单位是byte。由两个word模拟一个32

                  的偏移量,u_offset[0]为高16位,u_offset[1]为低16位;

(4)         u_dirpu_dent用来暂存搜索到的路径结点:

        0430: char *u_dirp;

 

0431: struct {

0432:      int u_ino;                            // inode指针

0433:      char u_name[DIRSIZ];      //文件名

0434: } u_dent;  

 

        即如果成功匹配,则u_dent中记录的是指定文件在其父目录里的目录项。

    

2.        访问一个文件的inode的典型方法如下:

1)从根目录(或当前目录)出发,读取其内容;

2)搜索其目录项,匹配路径的下个结点名字,获取该结点的inode

3)继续向下搜寻,直到获取最终文件的inode

 

3.        当搜索目的是“删除文件”时:

           匹配成功的话,返回值为父目录的inode

 

4.        当搜索目的是“添加文件”时:

1)如果在父目录中已经有同名的文件,则返回该文件的inode

2)否则,表示可以添加,则返回NULL,且

1 u_pdir设置为父目录的inode

2 u_offset[1]设置为文件内容的displacement,可以作为目录项起始地址来设置新加目录项;

   

 其代码比较令人费解,如下所示:

7603:    if(flag==1 && c=='\0') {

7604:         if(access(dp, IWRITE))

7605:              goto out;

7606:         u.u_pdir = dp;

7607:         if(eo)

7608:              u.u_offset[1] = eo-DIRSIZ-2; else

7609:              dp->i_flag =| IUPD;

7610:         return(NULL);

 

难懂的是7609行:

i.      为什么不设置u_offset[1]

ii.     父目录inode为何要设置IUPD标志?

 

          很简单,当eo0时,表示此时没有空目录项可用,所以需要扩大父目录的“目录项数组”。

i.     此时,offset[1]其实正好指向了“目录项数组”后面可以用于分配新目录项的位置;

ii.    父目录需要扩大“目录项数组”,即文件需要修改,故要设置IUPD标志。

 

 

博客地址:http://blog.csdn.net/cszhao1980

博客专栏地址:http://blog.csdn.net/column/details/lions-unix.html

 

 

你可能感兴趣的:((莱昂氏unix源代码分析导读-41)文件系统树状结构的形成)