一、进程与vfs对象之间的关系很重要:



1、VFS 中的每个文件、目录等都用且只用一个 索引节点inode表示,存放关于具体文件或者目录的一般信息。
2、每个索引节点对象都有一个索引节点号,这个号唯一地标识某个文件系统中的指定文件。
3、文件名可以随时更改,但是索引节点对文件是唯一的,并且随文件的存在而存在。每个文件又可以有多个文件名(ln建创链接)。即可以通过不同的文件名访问同一个文件。这里多个文件名对应一个文件的关系在数据结构中表示就是dentry和inode的关系。
4、具体文件系统的索引节点是存放在磁盘上的,是一种静态结构,要使用它,必须调入内存,填写VFS的索引节点,因此,也称VFS索引节点是动态节点。


Inode中不存储文件的名字,它只存储节点号;而dentry则保存有名字和与其对应的inode,所以就可以通过不同的dentry访问同一个inode。


进程每打开一个文件,就会有一个file结构与之对应。同一个进程可以多次打开同一个文件而得到多个不同的file结构,
多个进程也可以打开同一个文件得到多个不同的file结构。
file结构描述了被打开文件的属性,读写的偏移指针等等当前信息。


二、inode结构

每一个索引节点都由一个“struct inode”结构标识,下面认识一下inode的重要成员:

struct inode {
umode_t i_mode;    // 文件类型以及存取权限 
const struct inode_operations  *i_op;    //索引节点操作的函数指针  
struct super_block  *i_sb;            //超级块对象指针
struct address_space *i_mapping;   //address_space对象指针??
struct address_spacei_data;
unsigned long i_ino;          // 索引节点号
  dev_t i_rdev;  // 该文件系统的主设备号 
blkcnt_t i_blocks;          //块为单位的文件长度
loff_t i_size;       //文件长度

unsigned long i_state;      //索引节点状态标志
unsigned long dirtied_when; /* jiffies of first dirtying */

list_head i_dentry;  //引用索引节点的目录项对象链表头

const struct file_operations*i_fop; //文件操作函数指针

struct list_headi_devices;   //块设备指针
 
  struct block_device *i_bdev;    //块设备驱动程序指针

void *i_private;  // 私有数据指针
};


三、inode操作方法

索引节点关联的方法叫索引节点操作,由一个“structinode_operations”结构标识:

struct inode_operations {
struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);       //查找目录项。
int (*create) (struct inode *,struct dentry *,umode_t,struct nameidata *);  open(2) and creat(2)系统调用调用。
int (*link) (struct dentry *,struct inode *,struct dentry *);                      创建硬链接
int (*unlink) (struct inode *,struct dentry *);                                            unlink(2)系统调用调用。
int (*symlink) (struct inode *,struct dentry *,const char *);             symlink(2)系统调用调用。
int (*mkdir) (struct inode *,struct dentry *,umode_t);                      系统调用 mkdir(2)调用。
int (*rmdir) (struct inode *,struct dentry *);                                         
int (*mknod) (struct inode *,struct dentry *,umode_t,dev_t);
int (*rename) (struct inode *, struct dentry *, struct inode *, struct dentry *);  系统调用rename(2)调用
void (*truncate) (struct inode *);                修改与索引节点相关的文件的文件大小。

int (*permission) (struct inode *, int);             检查访问权限。
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
.................
} ____cacheline_aligned;


四、inode初始化

inode的查找、创建在《linux VFS 之二:超级块superblock》详细说明了。
这里以sdcardfs举例说明,inode的初始化,如下代码:

static struct inode *sdcardfs_iget(struct super_block *sb,
struct inode *lower_inode)
{
struct sdcardfs_inode_info *info;
struct inode *inode; /* the new inode to return */
int err;


/* in order for FAT emulation */
//struct sdcardfs_sb_info *sb_info = sb->s_fs_info;


inode = iget5_locked(sb, /* our superblock */     //inode的查找、创建
    /*
     * hashval: we use inode number, but we can
     * also use "(unsigned long)lower_inode"
     * instead.
     */
    lower_inode->i_ino, /* hashval */
    sdcardfs_inode_test,/* inode comparison function */
    sdcardfs_inode_set, /* inode init function */
    lower_inode); /* data passed to test+set fxns */
if (!inode) {
err = -EACCES;
iput(lower_inode);
return ERR_PTR(err);
}
/* if found a cached inode, then just return it */
if (!(inode->i_state & I_NEW))    // cache的inode,已经初始化过,直接返回。
 return inode;

inode->i_ino = lower_inode->i_ino;    //初始化索引号
if (!igrab(lower_inode)) {
err = -ESTALE;
return ERR_PTR(err);
}
sdcardfs_set_lower_inode(inode, lower_inode);   //记录低层文文件系统的inode,sdcardfs特有


inode->i_version++;
//*************初始化inode操作函数指针
/* use different set of inode ops for symlinks & directories */
if (S_ISDIR(lower_inode->i_mode))
inode->i_op = &sdcardfs_dir_iops;

else if (S_ISLNK(lower_inode->i_mode))
inode->i_op = &sdcardfs_symlink_iops;
else
inode->i_op = &sdcardfs_main_iops;
//*************初始化file操作函数指针***********//

/* use different set of file ops for directories */
if (S_ISDIR(lower_inode->i_mode))
inode->i_fop = &sdcardfs_dir_fops;
else
inode->i_fop = &sdcardfs_main_fops;
inode->i_mappng->a_ops = &sdcardfs_aops;

//初始化inode的访问时间
inode->i_atime.tv_sec = 0;
inode->i_atime.tv_nsec = 0;
inode->i_mtime.tv_sec = 0;
inode->i_mtime.tv_nsec = 0;
inode->i_ctime.tv_sec = 0;
inode->i_ctime.tv_nsec = 0;


//*************这边又初始化file操作函数指针,和上面有冲突?***********//
/* properly initialize special inodes */
if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
   S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) {
init_special_inode(inode, lower_inode->i_mode,
  lower_inode->i_rdev);
//printk(KERN_INFO "sdcardfs: %s(%d)-> i_mode=%o \n", __FUNCTION__, __LINE__, inode->i_mode);


    }

//从低层文件系统copy其它属性,用于初始化sdcardfs inode
/* all well, copy inode attributes */
fsstack_copy_attr_all(inode, lower_inode);
fsstack_copy_inode_size(inode, lower_inode);


fix_fat_permission(inode);

return inode;
}


Logo

更多推荐