首页 > 代码库 > 文件存储结构inode与RAM结构建立联系

文件存储结构inode与RAM结构建立联系

linux下一切皆文件,大致可分为以下几类:目录、普通文件、硬连接、软连接、字符设备、块设备、FIFO、Socket,其在物理存储体内存储按inode和数据块存储,inode代表元数据,是除实际数据外的所有(属性)数据。根据不同的文件类型有以下几种情况:

》对于常规文件,文件的数据存储在数据块中,其他数据(即属性)存储在inode中。

》对于目录,该目录下的所有文件名和目录名存储在数据块中,注意文件名保存在它所在目录的数据块中,除文件名之外,ls -l命令看到的其它信息都保存在该文件的inode中。注意这个概念:目录也是一种文件,是一种特殊类型的文件。

对于硬链接,其只是在硬链接所在目录的数据块中增加或修改文件名,并修改硬链接目标inode的链接数(ls显示属性的第二项),并不会增加inode或数据块。

》对于符号链接,如果目标路径名较短则直接保存在inode中以便更快地查找,如果目标路径名较长则分配一个数据块来保存。

》设备文件、FIFO和socket等特殊文件没有数据块,设备文件的主设备号和次设备号保存在inode中

inode结构体定义在linux/fs.h中:

/*
 * Keep mostly read-only and often accessed (especially for
 * the RCU path lookup and ‘stat‘ data) fields at the beginning
 * of the ‘struct inode‘
 */
struct inode {
    umode_t         i_mode;
    unsigned short      i_opflags;
    uid_t           i_uid;
    gid_t           i_gid;
    unsigned int        i_flags;

#ifdef CONFIG_FS_POSIX_ACL
    struct posix_acl    *i_acl;
    struct posix_acl    *i_default_acl;
#endif

    const struct inode_operations   *i_op;
    struct super_block  *i_sb;
    struct address_space    *i_mapping;

#ifdef CONFIG_SECURITY
    void            *i_security;
#endif

    /* Stat data, not accessed from path walking */
    unsigned long       i_ino;
    /*
     * Filesystems may only read i_nlink directly.  They shall use the
     * following functions for modification:
     *
     *    (set|clear|inc|drop)_nlink
     *    inode_(inc|dec)_link_count
     */
    union {
        const unsigned int i_nlink;
        unsigned int __i_nlink;
    };
    dev_t           i_rdev;
    struct timespec     i_atime;
    struct timespec     i_mtime;
    struct timespec     i_ctime;
    spinlock_t      i_lock; /* i_blocks, i_bytes, maybe i_size */
    unsigned short          i_bytes;
    blkcnt_t        i_blocks;
    loff_t          i_size;

#ifdef __NEED_I_SIZE_ORDERED
    seqcount_t      i_size_seqcount;
#endif

    /* Misc */
    unsigned long       i_state;
    struct mutex        i_mutex;

    unsigned long       dirtied_when;   /* jiffies of first dirtying */

    struct hlist_node   i_hash;
    struct list_head    i_wb_list;  /* backing dev IO list */
    struct list_head    i_lru;      /* inode LRU list */
    struct list_head    i_sb_list;
    union {
        struct list_head    i_dentry;
        struct rcu_head     i_rcu;
    };
    atomic_t        i_count;
    unsigned int        i_blkbits;
    u64         i_version;
    atomic_t        i_dio_count;
    atomic_t        i_writecount;
    const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
    struct file_lock    *i_flock;
    struct address_space    i_data;

#ifdef CONFIG_QUOTA
    struct dquot        *i_dquot[MAXQUOTAS];
#endif
    struct list_head    i_devices;
    union {
        struct pipe_inode_info  *i_pipe;
        struct block_device *i_bdev;
        struct cdev     *i_cdev;
    };

    __u32           i_generation;

#ifdef CONFIG_FSNOTIFY
    __u32           i_fsnotify_mask; /* all events this inode cares about */
    struct hlist_head   i_fsnotify_marks;
#endif

#ifdef CONFIG_IMA
    atomic_t        i_readcount; /* struct files open RO */
#endif
    void            *i_private; /* fs or device private pointer */
};

 ls -li显示属性各字段含义介绍

stat函数读取文件的inode,然后把inode中的各种文件属性填入一个struct stat结构体传出给调用者。ls或stat可查看inode属性。

struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */
               mode_t    st_mode;    /* protection */
               nlink_t   st_nlink;   /* number of hard links */
               uid_t     st_uid;     /* user ID of owner */
               gid_t     st_gid;     /* group ID of owner */
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */
               blksize_t st_blksize; /* blocksize for file system I/O */
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
               time_t    st_atime;   /* time of last access */
               time_t    st_mtime;   /* time of last modification */
               time_t    st_ctime;   /* time of last status change */
           };

普通文件

~$ls -li wang
588946 -rw-rw-r-- 1 yuxi yuxi 9045 Feb 12 18:37 wang 

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  file_name 

目录 

 712708 drwxrwxr-x 2 yuxi yuxi    4096 Oct  6 15:52 file

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  dir_name

硬链接

~$ln wang hard_wang
~$ls -li wang hard_wang
588946 -rwxrwxr-x 2 yuxi yuxi 9045 Feb 12 18:37 hard_wang
588946 -rwxrwxr-x 2 yuxi yuxi 9045 Feb 12 18:37 wang

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  file_name

符号链接

2011 lrwxrwxrwx  1 root root          15 Mar 19 10:01 stdout -> /proc/self/fd/1

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size(软链接文件名大小)  st_mtime  file_name 

字符设备

1904 crw-rw-rw-  1 root tty       5,   0 Mar 19 10:01 tty

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_rdev  st_mtime  dev_name

块设备

7502 brw-rw----  1 root disk      8,   0 Mar 19 10:01 sda

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_rdev  st_mtime  dev_name

socket

9252 srw-rw-rw-  1 root root           0 Mar 19 10:01 log

st_ino  file_type  st_mode  st_nlink  st_uid  st_gid  st_size  st_mtime  file_name

inode与RAM建立连接

所有文件都是通过open或类open函数将inode与file建立联系,release将file结构体的修改更新inode。用inode填充file结构体(file为RAM结构体),实现了物理结构体与RAM结构体的分离,之后的read、write等file_operations函数直接操作file结构体即可完成对文件的所有更改

int (*open) (struct inode *, struct file *);
extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, const struct cred *);
extern int dcache_dir_open(struct inode *, struct file *);
int (*release) (struct inode *, struct file *);

file结构体定义于linux/fs.h,如下:

struct file {
    /*   
     * fu_list becomes invalid after file_free is called and queued via
     * fu_rcuhead for RCU freeing
     */
    union {
        struct list_head    fu_list;
        struct rcu_head     fu_rcuhead;
    } f_u; 
    struct path     f_path;
#define f_dentry    f_path.dentry
#define f_vfsmnt    f_path.mnt
    const struct file_operations    *f_op;

    /*   
     * Protects f_ep_links, f_flags, f_pos vs i_size in lseek SEEK_CUR.
     * Must not be taken from IRQ context.
     */
    spinlock_t      f_lock;
#ifdef CONFIG_SMP
    int         f_sb_list_cpu;
#endif
    atomic_long_t       f_count;
    unsigned int        f_flags;
    fmode_t         f_mode;
    loff_t          f_pos;
    struct fown_struct  f_owner;
    const struct cred   *f_cred;
    struct file_ra_state    f_ra;

    u64         f_version;
#ifdef CONFIG_SECURITY
    void            *f_security;
#endif
    /* needed for tty driver, and maybe others */
    void            *private_data;

#ifdef CONFIG_EPOLL
    /* Used by fs/eventpoll.c to link all the hooks to this file */
    struct list_head    f_ep_links;
#endif /* #ifdef CONFIG_EPOLL */
    struct address_space    *f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
    unsigned long f_mnt_write_state;
#endif
};

字符文件open函数调用过程记录:

技术分享

 

 

参考:

1. linux虚拟文件系统vfs

2. ext2文件系统了解

3. inode表原数据,存储在物理存储体上

文件存储结构inode与RAM结构建立联系