zoukankan      html  css  js  c++  java
  • linux文件系统初探--Day4

    今天的内容主要是学习inode的基础知识。

    inode

    材料中总结了inode的一些基本要点:

    1. inode代表了一个文件及其metadata(时间戳,文件类型,文件大小等),但是不包括文件名;
    2. inode可以表示普通文件,目录文件,符号链接以及特殊文件;
    3. 通过完成VFS中inode_operations和file_operations的成员函数来完成inode的相关操作;
    4. 同时也需要完成inode中metadata的内容(uid,gid,owner,mode,timestamps等)。
    /*
     * 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;
    	kuid_t			i_uid;
    	kgid_t			i_gid;
    	unsigned int		i_flags;
            [--skipped--]
    	const struct inode_operations	*i_op;
    	struct super_block	*i_sb;
    	struct address_space	*i_mapping;
            [--skipped--]
    	/* Stat data, not accessed from path walking */
    	unsigned long		i_ino;
    	union {
    		const unsigned int i_nlink;
    		unsigned int __i_nlink;
    	};
    	dev_t			i_rdev;
    	loff_t			i_size;
    	struct timespec64	i_atime;
    	struct timespec64	i_mtime;
    	struct timespec64	i_ctime;
    	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
    	unsigned short          i_bytes;
    	u8			i_blkbits;
    	u8			i_write_hint;
    	blkcnt_t		i_blocks;
            [--skipped--]
    	atomic_t		i_count;
    	atomic_t		i_dio_count;
    	atomic_t		i_writecount;
    #ifdef CONFIG_IMA
    	atomic_t		i_readcount; /* struct files open RO */
    #endif
    	const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
    	struct file_lock_context	*i_flctx;
    	struct address_space	i_data;
    	struct list_head	i_devices;
    	union {
    		struct pipe_inode_info	*i_pipe;
    		struct block_device	*i_bdev;
    		struct cdev		*i_cdev;
    		char			*i_link;
    		unsigned		i_dir_seq;
    	};
    
    	__u32			i_generation;
            [--skipped--]
    } __randomize_layout;
    

    inode 的结构较为复杂,所以我们在这里进行一些简化。需要注意的是,上面提到的inode指的是内存中的inode,所以有些部分并不存在于外部存储中,这些信息由内核自身从底层文件系统读入信息时生成或动态建立。

    • i_atime、i_mtime、i_ctime:
      分别表示最后访问时间,数据段最后修改时间,最后修改inode的时间。
    • i_size:
      文件大小(字节)。
    • i_blocks:
      文件块数量,i_blocks = i_size / 块大小
    • i_ino:
      每个 VFS inode 都由一个唯一的编号标识,保存在i_ino中。
    • i_count:
      使用计数器,表示访问该inode的进程数目。
    • i_mode,i_uid,i_gid:
      文件访问权限和所有权。
    • i_rdev:
      一个数字,其中包含找到相关目标设备的信息。
    • i_devices:
      链表元素,使得字符设备或者块设备可以维护一个inode链表,其中每个inode代表一个设备文件,通过设备文件来访问对应的设备。
    • i_op,i_fop:
      i_op用于管理结构性的操作(例如删除文件)和文件相关的元数据(例如属性等);i_fop用于操作文件中包含的数据。

    内核提供了大量函数对inode进行操作,为此定义了一个函数集合抽象这些操作,这些操作接口保持不变,但是实际的操作根据文件系统的不同有所差异。所有的inode操作都由一个inode_operations抽象起来:

    struct inode_operations {
    	struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
    	const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
    	int (*permission) (struct inode *, int);
    	struct posix_acl * (*get_acl)(struct inode *, int);
    
    	int (*readlink) (struct dentry *, char __user *,int);
    
    	int (*create) (struct inode *,struct dentry *, umode_t, bool);
    	int (*link) (struct dentry *,struct inode *,struct dentry *);
    	int (*unlink) (struct inode *,struct dentry *);
    	int (*symlink) (struct inode *,struct dentry *,const char *);
    	int (*mkdir) (struct inode *,struct dentry *,umode_t);
    	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 *, unsigned int);
    	int (*setattr) (struct dentry *, struct iattr *);
    	int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
    	ssize_t (*listxattr) (struct dentry *, char *, size_t);
    	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
    		      u64 len);
    	int (*update_time)(struct inode *, struct timespec64 *, int);
    	int (*atomic_open)(struct inode *, struct dentry *,
    			   struct file *, unsigned open_flag,
    			   umode_t create_mode);
    	int (*tmpfile) (struct inode *, struct dentry *, umode_t);
    	int (*set_acl)(struct inode *, struct posix_acl *, int);
    } ____cacheline_aligned;
    

    day4 源码分析

    我们先来看day4的代码中新增的部分:

    #include <linux/ktime.h>
    #include <linux/timekeeping.h>
    struct inode *samplefs_get_inode(struct super_block *sb, int mode, dev_t dev)
    {
            struct inode * inode = new_inode(sb);
            struct timespec64 ts;
    
            if (inode) {
                    // 设置inode的一些成员
                    inode->i_mode = mode;
                    // inode->i_uid = current->fsuid;
                    inode->uid = current->cred->fsuid;
                    // inode->i_gid = current->fsgid;
                    inode->gid = current->cred->fsgid;
                    inode->i_blocks = 0;
                    ktime_get_ts64(&ts);
                    inode->i_atime = inode->i_mtime = inode->i_ctime = ts;
                    switch (mode & S_IFMT) {
                    default:
    			init_special_inode(inode, mode, dev);
    			break;
    /* We are not ready to handle files yet */
    /*                case S_IFREG:
    			inode->i_op = &sfs_file_inode_operations;
    			break; */
                    // 目前仅支持获取根目录的inode,并不支持常规文件。
                    case S_IFDIR:
                            inode->i_op = &simple_dir_inode_operations;
    
                            /* link == 2 (for initial ".." and "." entries) */
                            inode->__i_nlink++;
                            break;
                    }
            }
            return inode;
    }
    

    这个函数的逻辑比较简单,主要是创建,填充并返回一个inode。

    init_special_inode函数主要是为了填充i_mode,i_fop以及i_rdev。这三个成员上面已经解释过。

    void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
    {
    	inode->i_mode = mode;
    	if (S_ISCHR(mode)) {
    		inode->i_fop = &def_chr_fops;
    		inode->i_rdev = rdev;
    	} else if (S_ISBLK(mode)) {
    		inode->i_fop = &def_blk_fops;
    		inode->i_rdev = rdev;
    	} else if (S_ISFIFO(mode))
    		inode->i_fop = &pipefifo_fops;
    	else if (S_ISSOCK(mode))
    		;	/* leave it no_open_fops */
    	else
    		printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
    				  " inode %s:%lu
    ", mode, inode->i_sb->s_id,
    				  inode->i_ino);
    }
    EXPORT_SYMBOL(init_special_inode);
    

    而这个samplefs_get_inode函数在samplefs_fill_super中被调用,因为此时mode=S_ISDIR|0755,所以此时并不会设置i_fop和i_rdev。

    至此可以编译成功。

    参考资料

    sturct stat 结构体中 st_mode 的含义
    Linux 操作系统:进程数据结构(task_struct)
    inode的i_nlink

  • 相关阅读:
    微信开放平台:OpenAPI、云开发与基础管理能力升级
    腾讯刘颖:从容器到低代码,腾讯云原生技术演进历程
    十年老站长心声:我为什么选择把 Hexo 网站迁移到 Webify
    腾讯云发布微搭生态开放计划,与合作伙伴携手共创产业未来
    SQL Server附加数据库出现错误5123的正确解决方法
    数据分页获取(二)
    Select语句
    数据分页获取(一)
    SQL Server中行转列原理
    QT实现Linux下系统监控小工具之二
  • 原文地址:https://www.cnblogs.com/LuoboLiam/p/14321773.html
Copyright © 2011-2022 走看看