文件关系图

superblock object

struct super_block {
	/**
	 * 指向超级块链表的指针
	 */
	struct list_head	s_list;		/* Keep this first */
	/**
	 * 设备标识符
	 */
	dev_t			s_dev;		/* search index; _not_ kdev_t */
	/**
	 * 以字节为单位的块大小
	 */
	unsigned long		s_blocksize;
	/**
	 * 基本块设备驱动程序中的以字节为单位的块大小。
	 */
	unsigned long		s_old_blocksize;
	/**
	 * 以位为单位的块大小
	 */
	unsigned char		s_blocksize_bits;
	/**
	 * 脏标志
	 */
	unsigned char		s_dirt;
	/**
	 * 文件的最大长度
	 */
	unsigned long long	s_maxbytes;	/* Max file size */
	/**
	 * 文件系统类型。
	 */
	struct file_system_type	*s_type;
	/**
	 * 超级块方法
	 */
	struct super_operations	*s_op;
	/**
	 * 磁盘限额处理方法
	 */
	struct dquot_operations	*dq_op;
	/**
	 * 磁盘限额管理方法
	 */
 	struct quotactl_ops	*s_qcop;
	/**
	 * NFS使用的输出操作
	 */
	struct export_operations *s_export_op;
	/**
	 * 安装标志
	 */
	unsigned long		s_flags;
	/**
	 * 文件系统的魔数
	 */
	unsigned long		s_magic;
	/**
	 * 文件系统根目录的目录项
	 */
	struct dentry		*s_root;
	/**
	 * 卸载时使用的信号量
	 */
	struct rw_semaphore	s_umount;
	/**
	 * 保护超级块使用的信号量
	 */
	struct semaphore	s_lock;
	/**
	 * 引用计数
	 */
	int			s_count;
	/**
	 * 对超级块的索引节点进行同步的标志
	 */
	int			s_syncing;
	/**
	 * 对超级块的已安装文件系统进行同步的的标志
	 */
	int			s_need_sync_fs;
	/**
	 * 次引用计数。
	 */
	atomic_t		s_active;
	/**
	 * 超级块安全数据结构
	 */
	void                    *s_security;
	/**
	 * 超级块扩展属性结构的指针
	 */
	struct xattr_handler	**s_xattr;

	/**
	 * 所有索引节点链表
	 */
	struct list_head	s_inodes;	/* all inodes */
	/**
	 * 脏索引节点链表
	 */
	struct list_head	s_dirty;	/* dirty inodes */
	/**
	 * 等等写入磁盘的索引节点链表
	 */
	struct list_head	s_io;		/* parked for writeback */
	/**
	 * 匿名目录项链表,用于NFS
	 */
	struct hlist_head	s_anon;		/* anonymous dentries for (nfs) exporting */
	/**
	 * 文件对象链表
	 */
	struct list_head	s_files;

	/**
	 * 指向块设备驱动程序描述符的指针
	 */
	struct block_device	*s_bdev;
	/**
	 * 相同文件类型的超级块对象链表。
	 */
	struct list_head	s_instances;
	/**
	 * 磁盘限额的描述符
	 */
	struct quota_info	s_dquot;	/* Diskquota specific options */
	
	/**
	 * 冻结文件系统时使用的标志,用于强制设置一致性状态。
	 */
	int			s_frozen;
	/**
	 * 等待解冻的队列。
	 */
	wait_queue_head_t	s_wait_unfrozen;

	/**
	 * 包含超级块的块设备名称
	 */
	char s_id[32];				/* Informational name */

	/**
	 * 指向特定文件系统的超级块信息的指针。各文件系统自定义。
	 * 对ext2来说,是指向一个ext2_sb_info类型的结构。
	 */
	void 			*s_fs_info;	/* Filesystem private info */

	/*
	 * The next field is for VFS *only*. No filesystems have any business
	 * even looking at it. You had been warned.
	 */
	/**
	 * 当VFS通过目录重命名文件时使用的信号量。
	 */
	struct semaphore s_vfs_rename_sem;	/* Kludge */

	/* Granuality of c/m/atime in ns.
	   Cannot be worse than a second */
	/**
	 * c/m/atime的时间戳粒度。
	 */
	u32		   s_time_gran;
};

superblock operation tables

/**
 * 超级块操作方法
 */
struct super_operations {
	/**
	 * 为索引节点对象分配空间,包括具体文件系统的数据所需要的空间。
	 */
   	struct inode *(*alloc_inode)(struct super_block *sb);
	/**
	 * 释放索引节点对象。
	 */
	void (*destroy_inode)(struct inode *);

	/**
	 * 用磁盘上的数据填充索引节点对象的字段。
	 * 索引节点对象的i_ino字段标识从磁盘上要索引节点。
	 */
	void (*read_inode) (struct inode *);

  	/**
  	 * 当索引节点标记为脏时调用。日志文件系统用来更新磁盘上的文件系统日志。
  	 */
   	void (*dirty_inode) (struct inode *);
	/**
	 * 更新索引节点对象的内容。flag参数表示IO操作是否应当同步。
	 */
	int (*write_inode) (struct inode *, int);
	/**
	 * 减少索引节点的引用计数值。
	 */
	void (*put_inode) (struct inode *);
	/**
	 * 当最后一个用户释放索引节点时调用。通常调用generic_drop_inode。
	 */
	void (*drop_inode) (struct inode *);
	/**
	 * 删除内存中的索引节点和磁盘上的文件数据和元数据。
	 */
	void (*delete_inode) (struct inode *);
	/**
	 * 由于文件系统被卸载而释放对超级块的引用。
	 */
	void (*put_super) (struct super_block *);
	/**
	 * 更新文件系统超级块。
	 */
	void (*write_super) (struct super_block *);
	/**
	 * 清除文件系统以更新磁盘上文件系统数据结构
	 */
	int (*sync_fs)(struct super_block *sb, int wait);
	/**
	 * 阻塞对文件系统的修改,并用指定对象的内容更新超级块。
	 * 当文件系统被冻结时调用。例如LVM会调用它。
	 */
	void (*write_super_lockfs) (struct super_block *);
	/**
	 * 取消由write_super_lockfs阻塞。
	 */
	void (*unlockfs) (struct super_block *);
	/**
	 * 返回文件系统的统计信息。
	 */
	int (*statfs) (struct super_block *, struct kstatfs *);
	/**
	 * 用新的选项重新安装文件系统。
	 */
	int (*remount_fs) (struct super_block *, int *, char *);
	/**
	 * 撤销磁盘索引节点时调用。
	 */
	void (*clear_inode) (struct inode *);
	/**
	 * 开始卸载操作。只在NFS中使用。
	 */
	void (*umount_begin) (struct super_block *);

	/**
	 * 显示特定文件系统的选项。
	 */
	int (*show_options)(struct seq_file *, struct vfsmount *);

	/**
	 * 读取限额设置。
	 */
	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
	/**
	 * 修改限额配置。
	 */
	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
};

inode object

The inode object represents all the information needed by the kernel to manipulate a file or directory.
The inode object is represented by struct inode and is defined in <linux/fs.h>

/**
 * 内核用该结构在内部表示一个文件。它与file不同。file表示的的文件描述符。
 * 对单个文件,可能会有许多个表示打开的文件描述符的filep结构,但是它们都指向单个inode结构。
 */
struct inode {
	/**
	 * 通过此字段将对象放入哈希表。
	 */
	struct hlist_node	i_hash;
	/**
	 * 通过此字段将队列链入不同状态的链表中。
	 */
	struct list_head	i_list;
	/**
	 * 通过此字段将其链入到超级块的inode链表中。
	 */
	struct list_head	i_sb_list;
	/**
	 * 引用索引节点的目录项对象链表头。
	 */
	struct list_head	i_dentry;
	/**
	 * 索引节点编号。
	 */
	unsigned long		i_ino;
	/**
	 * 引用计数器。
	 */
	atomic_t		i_count;
	/**
	 * 文件类型与访问权限。
	 */
	umode_t			i_mode;
	/**
	 * 硬链接数目。
	 */
	unsigned int		i_nlink;
	/**
	 * 所有者ID
	 */
	uid_t			i_uid;
	/**
	 * 所有者组标识符。
	 */
	gid_t			i_gid;
	/**
	 * 对表示设备文件的inode结构,该字段包含了真正的设备编号。
	 */
	dev_t			i_rdev;
	/**
	 * 文件的字节数。
	 */
	loff_t			i_size;
	/**
	 * 上次访问文件的时间。
	 */
	struct timespec		i_atime;
	/**
	 * 上次与文件的时间。
	 */
	struct timespec		i_mtime;
	/**
	 * 上次修改索引节点的时间。
	 */
	struct timespec		i_ctime;
	/**
	 * 块的位数。
	 */
	unsigned int		i_blkbits;
	/**
	 * 块的字节数。
	 */
	unsigned long		i_blksize;
	/**
	 * 版本号,每次使用后递增。
	 */
	unsigned long		i_version;
	/**
	 * 文件的块数。
	 */
	unsigned long		i_blocks;
	/**
	 * 文件最后一个块的字节数。
	 */
	unsigned short          i_bytes;
	/**
	 * 非0表示文件是一个套接字。
	 */
	unsigned char		i_sock;
	/**
	 * 保护索引节点某些字段的自旋锁。
	 */
	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
	/**
	 * 保护索引节点的信号量。
	 */
	struct semaphore	i_sem;
	/**
	 * 在直接IO文件操作中避免出现竞争条件的读写信号量。
	 */
	struct rw_semaphore	i_alloc_sem;
	/**
	 * 索引节点的操作。
	 */
	struct inode_operations	*i_op;
	/**
	 * 缺省文件操作。
	 */
	struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
	/**
	 * inode所在的超级块。
	 */
	struct super_block	*i_sb;
	/**
	 * 文件锁链表,通过此字段将文件上的所有锁链接成一个单链表。
	 */
	struct file_lock	*i_flock;
	/**
	 * 指向address_space对象的指针。
	 */
	struct address_space	*i_mapping;
	/**
	 * 文件的address_space对象。
	 */
	struct address_space	i_data;
#ifdef CONFIG_QUOTA
	/**
	 * 索引节点的磁盘限额。
	 */
	struct dquot		*i_dquot[MAXQUOTAS];
#endif
	/* These three should probably be a union */
	/**
	 * 用于具体的字符或块设备的索引节点链表指针。
	 */
	struct list_head	i_devices;
	/**
	 * 如果内核是一个管道则非0
	 */
	struct pipe_inode_info	*i_pipe;
	/**
	 * 指向块设备驱动程序的指针。
	 */
	struct block_device	*i_bdev;
	/**
	 * 表示字符设备的内部数据结构。当inode指向一个字符设备文件时,该字段包含了指向struct cdev结构的指针。
	 */
	struct cdev		*i_cdev;
	/**
	 * 次设备号索引。
	 */
	int			i_cindex;

	/**
	 * 索引节点版本号。由某些文件系统使用。
	 */
	__u32			i_generation;

#ifdef CONFIG_DNOTIFY
	/**
	 * 目录通知事件掩码。
	 */
	unsigned long		i_dnotify_mask; /* Directory notify events */
	/**
	 * 用于目录通知。
	 */
	struct dnotify_struct	*i_dnotify; /* for directory notifications */
#endif

	/**
	 * 索引节点状态标志。
	 */
	unsigned long		i_state;
	/**
	 * 索引节点弄脏的时间,以jiffies为单位。
	 */
	unsigned long		dirtied_when;	/* jiffies of first dirtying */

	/**
	 * 文件系统的安装标志。
	 */
	unsigned int		i_flags;

	/**
	 * 用于写进程的引用计数。
	 */
	atomic_t		i_writecount;
	/**
	 * 索引节点安全结构。
	 */
	void			*i_security;
	/**
	 * 文件系统私有数据指针。
	 */
	union {
		void		*generic_ip;
	} u;
#ifdef __NEED_I_SIZE_ORDERED
	/**
	 * SMP系统为i_size字段获取一致性时使用的顺序计数器。
	 */
	seqcount_t		i_size_seqcount;
#endif
};

dentry object

/**
 * 内核用该结构在内部表示一个文件。它与file不同。file表示的的文件描述符。
 * 对单个文件,可能会有许多个表示打开的文件描述符的filep结构,但是它们都指向单个inode结构。
 */
struct inode {
	/**
	 * 通过此字段将对象放入哈希表。
	 */
	struct hlist_node	i_hash;
	/**
	 * 通过此字段将队列链入不同状态的链表中。
	 */
	struct list_head	i_list;
	/**
	 * 通过此字段将其链入到超级块的inode链表中。
	 */
	struct list_head	i_sb_list;
	/**
	 * 引用索引节点的目录项对象链表头。
	 */
	struct list_head	i_dentry;
	/**
	 * 索引节点编号。
	 */
	unsigned long		i_ino;
	/**
	 * 引用计数器。
	 */
	atomic_t		i_count;
	/**
	 * 文件类型与访问权限。
	 */
	umode_t			i_mode;
	/**
	 * 硬链接数目。
	 */
	unsigned int		i_nlink;
	/**
	 * 所有者ID
	 */
	uid_t			i_uid;
	/**
	 * 所有者组标识符。
	 */
	gid_t			i_gid;
	/**
	 * 对表示设备文件的inode结构,该字段包含了真正的设备编号。
	 */
	dev_t			i_rdev;
	/**
	 * 文件的字节数。
	 */
	loff_t			i_size;
	/**
	 * 上次访问文件的时间。
	 */
	struct timespec		i_atime;
	/**
	 * 上次与文件的时间。
	 */
	struct timespec		i_mtime;
	/**
	 * 上次修改索引节点的时间。
	 */
	struct timespec		i_ctime;
	/**
	 * 块的位数。
	 */
	unsigned int		i_blkbits;
	/**
	 * 块的字节数。
	 */
	unsigned long		i_blksize;
	/**
	 * 版本号,每次使用后递增。
	 */
	unsigned long		i_version;
	/**
	 * 文件的块数。
	 */
	unsigned long		i_blocks;
	/**
	 * 文件最后一个块的字节数。
	 */
	unsigned short          i_bytes;
	/**
	 * 非0表示文件是一个套接字。
	 */
	unsigned char		i_sock;
	/**
	 * 保护索引节点某些字段的自旋锁。
	 */
	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
	/**
	 * 保护索引节点的信号量。
	 */
	struct semaphore	i_sem;
	/**
	 * 在直接IO文件操作中避免出现竞争条件的读写信号量。
	 */
	struct rw_semaphore	i_alloc_sem;
	/**
	 * 索引节点的操作。
	 */
	struct inode_operations	*i_op;
	/**
	 * 缺省文件操作。
	 */
	struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
	/**
	 * inode所在的超级块。
	 */
	struct super_block	*i_sb;
	/**
	 * 文件锁链表,通过此字段将文件上的所有锁链接成一个单链表。
	 */
	struct file_lock	*i_flock;
	/**
	 * 指向address_space对象的指针。
	 */
	struct address_space	*i_mapping;
	/**
	 * 文件的address_space对象。
	 */
	struct address_space	i_data;
#ifdef CONFIG_QUOTA
	/**
	 * 索引节点的磁盘限额。
	 */
	struct dquot		*i_dquot[MAXQUOTAS];
#endif
	/* These three should probably be a union */
	/**
	 * 用于具体的字符或块设备的索引节点链表指针。
	 */
	struct list_head	i_devices;
	/**
	 * 如果内核是一个管道则非0
	 */
	struct pipe_inode_info	*i_pipe;
	/**
	 * 指向块设备驱动程序的指针。
	 */
	struct block_device	*i_bdev;
	/**
	 * 表示字符设备的内部数据结构。当inode指向一个字符设备文件时,该字段包含了指向struct cdev结构的指针。
	 */
	struct cdev		*i_cdev;
	/**
	 * 次设备号索引。
	 */
	int			i_cindex;

	/**
	 * 索引节点版本号。由某些文件系统使用。
	 */
	__u32			i_generation;

#ifdef CONFIG_DNOTIFY
	/**
	 * 目录通知事件掩码。
	 */
	unsigned long		i_dnotify_mask; /* Directory notify events */
	/**
	 * 用于目录通知。
	 */
	struct dnotify_struct	*i_dnotify; /* for directory notifications */
#endif

	/**
	 * 索引节点状态标志。
	 */
	unsigned long		i_state;
	/**
	 * 索引节点弄脏的时间,以jiffies为单位。
	 */
	unsigned long		dirtied_when;	/* jiffies of first dirtying */

	/**
	 * 文件系统的安装标志。
	 */
	unsigned int		i_flags;

	/**
	 * 用于写进程的引用计数。
	 */
	atomic_t		i_writecount;
	/**
	 * 索引节点安全结构。
	 */
	void			*i_security;
	/**
	 * 文件系统私有数据指针。
	 */
	union {
		void		*generic_ip;
	} u;
#ifdef __NEED_I_SIZE_ORDERED
	/**
	 * SMP系统为i_size字段获取一致性时使用的顺序计数器。
	 */
	seqcount_t		i_size_seqcount;
#endif
};

file object

linux/fs.h

/**
 * 代表一个打开的文件。由内核在open时创建。当文件的所有实例都被关闭后,才释放该结构。
 */
struct file {
	/**
	 * 用于通用文件对象链表的指针。
	 */
	struct list_head	f_list;
	/**
	 * 文件对应的目录项结构。除了用filp->f_dentry->d_inode的方式来访问索引节点结构之外,设备驱动程序的开发者们一般无需关心dentry结构。
	 */
	struct dentry		*f_dentry;
	/**
	 * 含有该文件的已经安装的文件系统。
	 */
	struct vfsmount         *f_vfsmnt;
	/**
	 * 与文件相关的操作。内核在执行open操作时,对这个指针赋值,以后需要处理这些操作时就读取这个指针。
	 * 不能为了方便而保存起来。也就是说,可以在任何需要的时候修改文件的关联操作。即"方法重载"。
	 */
	struct file_operations	*f_op;
	/**
	 * 文件对象的引用计数。
	 * 指引用文件对象的进程数。内核也可能增加此计数。
	 */
	atomic_t		f_count;
	/**
	 * 文件标志。如O_RONLY、O_NONBLOCK和O_SYNC。为了检查用户请求是否非阻塞式的操作,驱动程序需要检查O_NONBLOCK标志,其他标志较少用到。
	 * 检查读写权限应该查看f_mode而不是f_flags。
	 */
	unsigned int 		f_flags;
	/** 
	 * 文件模式。FMODE_READ和FMODE_WRITE分别表示读写权限。
	 */
	mode_t			f_mode;
	/**
	 * 网络写操作的错误码。
	 */
	int			f_error;
	/**
	 * 当前的读写位置。它是一个64位数。如果驱动程序需要知道文件中的当前位置,可以读取这个值但是不要去修改它。
	 * read/write会使用它们接收到的最后那个指针参数来更新这一位置。
	 */
	loff_t			f_pos;
	/**
	 * 通过信号进行邋IO进程通知的数据。
	 */
	struct fown_struct	f_owner;
	/**
	 * 用户的UID和GID.
	 */
	unsigned int		f_uid, f_gid;
	/**
	 * 文件的预读状态。
	 */
	struct file_ra_state	f_ra;

	/**
	 * 一次操作能读写的最大字节数。当前设置为2^31-1
	 */
	size_t			f_maxcount;
	/**
	 * 版本号,每次使用后递增。
	 */
	unsigned long		f_version;
	/**
	 * 文件对象的安全结构指针。
	 */
	void			*f_security;

	/* needed for tty driver, and maybe others */
	/**
	 * open系统调用在调用驱动程序的open方法前将这个指针置为NULL。驱动程序可以将这个字段用于任何目的或者忽略这个字段。
	 * 驱动程序可以用这个字段指向已分配的数据,但是一定要在内核销毁file结构前在release方法中释放内存。
	 * 它是跨系统调用时保存状态的非常有用的资源。
	 */
	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;
	/**
	 * 保护f_ep_links的自旋锁。
	 */
	spinlock_t		f_ep_lock;
#endif /* #ifdef CONFIG_EPOLL */
	/**
	 * 指向文件地址空间的对象。
	 */
	struct address_space	*f_mapping;
};

files_struct

/*
 * Open file table structure
 */
/**
 * 进程当前打开的文件。
 */
struct files_struct {
		/**
		 * 共享该表的进程数目。
		 */
        atomic_t count;
		/**
		 * 保护该表的读写自旋锁。
		 */
        spinlock_t file_lock;     /* Protects all the below members.  Nests inside tsk->alloc_lock */
		/**
		 * 文件对象的当前最大编号。
		 */
        int max_fds;
		/**
		 * 文件描述符的当前最大编号。
		 */
        int max_fdset;
		/**
		 * 上次分配的最大文件描述符加1.
		 */
        int next_fd;
		/**
		 * 本进程文件对象数组指针。
		 */
        struct file ** fd;      /* current fd array */
		/**
		 * exec时需要关闭的文件描述符指针。
		 */
        fd_set *close_on_exec;
		/**
		 * 打开文件描述符的指针。
		 */
        fd_set *open_fds;
		/**
		 * 执行exec时需要关闭的文件描述符的初始集合。
		 */
        fd_set close_on_exec_init;
		/**
		 * 文件描述符的初始集合。
		 */
        fd_set open_fds_init;
		/**
		 * 文件对象指针的初始化数组。
		 */
        struct file * fd_array[NR_OPEN_DEFAULT];
};

参考

filesystem manager 文件系统及 Socket 源码解析