Four objects of linux virtual file system:
1) super block
2) Inode
3) Directory entry (dentry)
4) File object (file)
super_block
/*The super block represents the entire file system. The super block is the control block of the file system. It has the information of the entire file system. All inode s of a file system must be connected to the super block, It can be said that a super block represents a file system */ struct super_block { struct list_head s_list; /* Keep this first A two-way circular linked list, put all super_block connected, a super_block represents a file system on linux, On this list are all the file systems recorded on linux.*/ dev_t s_dev; /* search index; _not_ kdev_t The block device identifier that contains the specific file system. For example, for / dev/hda1, the device identifier is 0x301*/ unsigned char s_blocksize_bits;//above size The size takes up bits. For example, 512 bytes is 9 bits unsigned long s_blocksize;//The size of the data block in the file system, in bytes loff_t s_maxbytes; /* Max file size Maximum allowed file size (bytes) */ struct file_system_type *s_type;//file system type ext2 still fat32 ? ""File system" and "file system type" are different! A file system type can include many file systems, that is, many super_block const struct super_operations *s_op;//A collection of functions for superblock operations that point to a specific specific file system const struct dquot_operations *dq_op;//A collection of functions that point to a specific file system for quota operations const struct quotactl_ops *s_qcop;//A method for configuring disk quotas to handle requests from user space const struct export_operations *s_export_op; unsigned long s_flags; unsigned long s_iflags; /* internal SB_I_* flags */ unsigned long s_magic;//Identification different from other file systems struct dentry *s_root;//A directory entry pointing to the specific file system installation directory struct rw_semaphore s_umount;//Synchronize reads and writes to superblocks int s_count;//Use count of superblocks atomic_t s_active;//Reference count #ifdef CONFIG_SECURITY void *s_security; #endif const struct xattr_handler **s_xattr; struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */ struct list_head s_mounts; /* list of mounts; _not_ for fs use */ struct block_device *s_bdev;//Points to the block device on which the file system is mounted struct backing_dev_info *s_bdi; struct mtd_info *s_mtd; struct hlist_node s_instances; unsigned int s_quota_types; /* Bitmask of supported quota types */ struct quota_info s_dquot; /* Diskquota specific options Disk quota related options */ struct sb_writers s_writers; char s_id[32]; /* Informational name */ u8 s_uuid[16]; /* UUID */ void *s_fs_info; /* Filesystem private info */ unsigned int s_max_links; fmode_t s_mode; /* Granularity of c/m/atime in ns. Cannot be worse than a second */ u32 s_time_gran; /* * The next field is for VFS *only*. No filesystems have any business * even looking at it. You had been warned. */ struct mutex s_vfs_rename_mutex; /* Kludge */ /* * Filesystem subtype. If non-empty the filesystem type field * in /proc/mounts will be "type.subtype" */ char *s_subtype; /* * Saved mount options for lazy filesystems using * generic_show_options() */ char __rcu *s_options; const struct dentry_operations *s_d_op; /* default d_op for dentries */ /* * Saved pool identifier for cleancache (-1 means none) */ int cleancache_poolid; struct shrinker s_shrink; /* per-sb shrinker handle */ /* Number of inodes with nlink == 0 but still referenced */ atomic_long_t s_remove_count; /* Being remounted read-only */ int s_readonly_remount; /* AIO completions deferred from interrupt context */ struct workqueue_struct *s_dio_done_wq; struct hlist_head s_pins; /* * Context in which to interpret filesystem uids, gids, * quotas, device nodes, extended attributes and security * labels. */ struct user_namespace *s_user_ns; /* * Keep the lru lists last in the structure so they always sit on their * own individual cachelines. */ struct list_lru s_dentry_lru ____cacheline_aligned_in_smp; struct list_lru s_inode_lru ____cacheline_aligned_in_smp; struct rcu_head rcu; struct work_struct destroy_work; struct mutex s_sync_lock; /* sync serialisation lock */ /* * Indicates how deep in a filesystem stack this SB is */ int s_stack_depth; /* s_inode_list_lock protects s_inodes */ spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp; struct list_head s_inodes; /* all inodes */ };
Inode:
/* * Keep mostly read-only and often accessed (especially for * the RCU path lookup and 'stat' data) fields at the beginning * of the 'struct inode' inode There are two types: one is the inode of VFS and the other is the inode of specific file system. The former is in memory and the latter is on disk. So every time, you actually call inodes in the disk into inodes that fill the memory, This is the disk file inode used. The size of each inode node is generally 128 bytes or 256 bytes. The total number of inode nodes is given during formatting (Modern OS can change dynamically). Generally, one inode is set every 2KB. In general, there are few files less than 2KB in the file system, so the reservation is divided according to 2KB. Generally, inodes can't be used up. So inodes have a default number when the file system is installed, Later, it will change according to the actual needs inode The number is unique and represents different files. In fact, when accessing files inside Linux, they are accessed through the inode number. The so-called file name is only easy for users to use. When we open a file, first, the system finds the inode number corresponding to the file name; Then, the inode information is obtained through the inode number. Finally, the inode finds the block where the file data is located, You can now process the file data. inode Relationship with files: when a file is created, an inode is assigned to the file. An inode only corresponds to one actual file, and a file will have only one inode. inodes The maximum number is the maximum number of files. */ struct inode { umode_t i_mode;//File type and access rights unsigned short i_opflags; kuid_t i_uid;//File owner label kgid_t i_gid;//Group label of the file 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;//Set of inode operation functions struct super_block *i_sb;//inode Superblock pointer to the owning file system struct address_space *i_mapping;//Indicates who the page is requested from and describes the page in the page cache #ifdef CONFIG_SECURITY void *i_security; #endif /* Stat data, not accessed from path walking */ unsigned long i_ino;//Inode number, each inode Are unique /* * 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;//Actual equipment identification loff_t i_size;//inode The size of the file represented, in bytes struct timespec i_atime;//Last access time of file struct timespec i_mtime;//Last modification time of file struct timespec i_ctime;//inode Last modification time spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned short i_bytes;//The number of bytes of the last block in the file unsigned int i_blkbits;//Block size in bytes blkcnt_t i_blocks;//Number of blocks occupied by the file #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 */ unsigned long dirtied_time_when; struct hlist_node i_hash;//point hash Linked list pointer for inode of hash surface struct list_head i_io_list; /* backing dev IO list */ #ifdef CONFIG_CGROUP_WRITEBACK struct bdi_writeback *i_wb; /* the associated cgroup wb */ /* foreign inode detection, see wbc_detach_inode() */ int i_wb_frn_winner; u16 i_wb_frn_avg_time; u16 i_wb_frn_history; #endif struct list_head i_lru; /* inode LRU list */ struct list_head i_sb_list; union { struct hlist_head i_dentry;//Pointer to the table of contents. Note one inodes Can correspond to multiple dentry,Because an actual file may be linked to other files, //Then there will be another one dentry,This linked list is to combine all with Ben inode Relevant dentry All connected struct rcu_head i_rcu; }; u64 i_version;//Version number atomic_t i_count;//Reference count atomic_t i_dio_count; atomic_t i_writecount;//Record how many processes open this file in writing mode #ifdef CONFIG_IMA atomic_t i_readcount; /* struct files open RO */ #endif const struct file_operations *i_fop; /* former ->i_op->default_file_ops File operation*/ struct file_lock_context *i_flctx; struct address_space i_data; struct list_head i_devices;//Equipment linked list. A linked list of devices that share the same driver union { struct pipe_inode_info *i_pipe;//To a pipe file (used if the file is a pipe file) struct block_device *i_bdev;//Pointer to a block device file (used if the file is a block device file) struct cdev *i_cdev;//Pointer to a character device file (used if the file is a character device) char *i_link;//link }; __u32 i_generation; #ifdef CONFIG_FSNOTIFY __u32 i_fsnotify_mask; /* all events this inode cares about */ struct hlist_head i_fsnotify_marks; #endif void *i_private; /* fs or device private pointer */ };
dentry:
/* dentry It represents the relationship between different levels and is also the structure used by the link. dentry through d_parent to form a link relationship with the parent directory, Adopted d_op to store the file operations of the corresponding actual file system, such as create, delete, open, read and write, etc. d_sb points to the superblock of the actual file system, This structure has been described in detail above. d_inode points to the corresponding inode, d_name indicates the file name of the file. An effective dentry structure must have an inode structure, because a directory item either represents a file or a directory, and the directory is actually a file. Therefore, as long as the dentry structure is valid, its pointer D_ Inodes must point to an inode structure. However, inodes can correspond to multiple */ struct dentry { /* RCU lookup touched fields */ unsigned int d_flags; /* protected by d_lock Directory item cache ID, DCache is preferred_ UNUSED DCACHE_ Referenced et al */ seqcount_t d_seq; /* per dentry seqlock */ struct hlist_bl_node d_hash; /* lookup hash list The kernel uses dentry_hashtable manages dentry, dentry_hashtable is a list_ A linked list composed of head, After a dentry is created, it passes D_ The hash link enters the linked list of the corresponding hash value.*/ struct dentry *d_parent; /*Directory entry of parent directory */ struct qstr d_name;//Catalog item name struct inode *d_inode; /* Inode associated with the directory item where the name belongs to - null is * negative */ unsigned char d_iname[DNAME_INLINE_LEN]; /* Store short file names small names */ /* Ref lookup also touches following */ struct lockref d_lockref; /* per-dentry lock and refcount */ const struct dentry_operations *d_op;//Catalog item operation function set struct super_block *d_sb; /* The root of the dentry tree The superblock of the file system to which this directory entry belongs*/ unsigned long d_time; /* used by d_revalidate Time to become valid again! Note that this dentry is valid as long as the operation is successful, otherwise it is invalid*/ void *d_fsdata; /* fs-specific data File system private data */ struct list_head d_lru; /*LRU list of recently unused directory items */ struct list_head d_child; /* child of parent list The directory entry is added to the parent directory through D_ In subdirs*/ struct list_head d_subdirs; /* our children All child directory chain headers of this directory */ /* * d_alias and d_rcu can share memory A valid dentry must be associated with an inode, but an inode can correspond to multiple dentries because a file can be linked to other files, Therefore, the dentry is linked to the I in its own inode structure through this field_ In dentry linked list */ union { struct hlist_node d_alias; /* inode alias list This dentry is linked to the I in its own inode structure through this field_ In dentry linked list */ struct rcu_head d_rcu; } d_u; };
files
struct path { struct vfsmount *mnt; struct dentry *dentry; };
struct file { union { struct llist_node fu_llist; struct rcu_head fu_rcuhead; } f_u;//Pointer to the linked list of common file objects struct path f_path;//Indicates the installed file system of the file vfsmount And file related directory entry objects dentry struct inode *f_inode; /* cached value */ const struct file_operations *f_op;///*Pointer to file operation table --Function pointer*/ /* * Protects f_ep_links, f_flags. * Must not be taken from IRQ context. */ spinlock_t f_lock; atomic_long_t f_count;//Indicates the reference count of the open file unsigned int f_flags;//Indicates the permission to open the file fmode_t f_mode;//Set the access mode to the file,For example: read only, write only struct mutex f_pos_lock; loff_t f_pos;//Indicates the location of the current read / write file struct fown_struct f_owner;//The function of this structure is through signal processing I/O Asynchronous operation of data for time notification;Record a process ID,When something is sent, send it to the ID Process signal const struct cred *f_cred; struct file_ra_state f_ra;//File pre reading status, the main data structure used by the file pre reading algorithm. When a file is opened, f_ra It's out perv_page(Default to-1)and ra_apges(The maximum amount of prefetch allowed for this file)Except for these two fields, all other West ends are set to 0 u64 f_version;//The version number of the record file is automatically incremented after each use #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; struct list_head f_tfile_llink; #endif /* #ifdef CONFIG_EPOLL */ struct address_space *f_mapping; } __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
files_struct:
struct fdtable { unsigned int max_fds; struct file __rcu **fd; /* current fd array */ unsigned long *close_on_exec; unsigned long *open_fds; unsigned long *full_fds_bits; struct rcu_head rcu; }; /* * Open file table structure */ struct files_struct { /* * read mostly part */ atomic_t count;/* The number of processes sharing the table */ bool resize_in_progress; wait_queue_head_t resize_wait; /*Including a struct fdtable variable instance and a struct fdtable type pointer; The member variable close in struct fdtable_ on_ exec,open_fds and fd point to struct files respectively_ In struct Member close_on_exec_init,open_fds_init and fd_array*/ struct fdtable __rcu *fdt; struct fdtable fdtab; /* * written part on a separate cache line in SMP */ spinlock_t file_lock ____cacheline_aligned_in_smp; /* Protect all of the following domains from being in TSK - > alloc_ Nesting in lock*/ int next_fd;/*Allocated file descriptor plus 1*/ unsigned long close_on_exec_init[1];/*Points to the file descriptor that needs to be closed when exec() is executed*/ unsigned long open_fds_init[1];/*Pointer to open file descriptor*/ unsigned long full_fds_bits_init[1];/*Initial set of file descriptors*/ struct file __rcu * fd_array[NR_OPEN_DEFAULT];;/* The initialization array of file object pointers is dynamically allocated when it is not used enough by default*/ /*Typically, the fd field points to files_ fd of struct structure_ Array field, which includes 32 file object pointers. If the number of files opened by the process is more than 32, the kernel allocates a new and larger file pointer array, And store its address in the fd field, and the kernel also updates max_ The value of the FDS field.*/ };
In linux system, there is a preliminary limit on the number of files opened by a process, that is, the number of file descriptors is initially maximized, that is, a process can only open NR_OPEN_DEFAULT files, 32 on 32-bit machines and 64 on 64 bit machines. Files above_ The initialization of struct reflects the kernel structure description of the file that the process can open. It should be noted here that this is not limited to static initialization like the above, but also when the init process fork s a child process (files_struct is dynamically allocated at this time).
do_fork------>copy_process |------>dup_task_struct------>alloc_task_struct |------>copy_files------>dup_fd
That is, call alloc first_ task_struct assigns a task_struct structure instance, and then use alloc_files to allocate and initialize files_struct variable instance.
Files above_ There is no essential difference between struct initialization and static initialization in the above example:
The statement fdt = & newf - > fdtab takes out the pointer of the struct fdtable instance variable fdtab of newf, and then passes RCU_ assign_ The pointer function assigns a value to newf - > fdt, then newf - > fdt still points to the struct fdtable instance variable in itself, and the member of fdt is close_on_exec,open_ The same is true for FDS and fd.
When performing struct files_ During the extension of struct, a new struct fdtable will be allocated. For the convenience of description, the following variable is represented by pointer and nfdt. In addition, the fd array meeting the expansion requirements (i.e. struct file array) and the bitmap description close relative to fd are allocated_ on_ exec,open_fds storage space.
Then the newly allocated close_on_exec,open_ The FDS, fd space pointer is assigned to nfdt - > close_on_exec,nfdt->open_fds and nfdt - > fd. Notice the close here_ on_ exec,open_fds and close during initialization above_ on_ exec_ init,open_fds_init differences:
close_on_exec,open_ The maximum value of FDS is in bit__ FDSET_ Long, the actual value is 1024 bits, that is, the maximum number of file descriptors is 1024. However, they are also allocated on demand and are consistent with the size of the file array. The allocated actual value will be assigned to nfdt - > max at the same time_ fds.
After allocating and initializing the new struct fdtable variable, the struct files originally pointed to the fdtab_ The struct pointer member fdt will be adjusted to point to the newly allocated struct fdtable variable. At this time, struct files_ The struct instance variable contains two struct fdtable storage areas: one is its own, and the other is newly allocated, which is pointed to by fdt.
After performing the above operations, the relationship is as follows:
The storage area with the same color in the figure above represents that the contents of the two are consistent. That is, after performing the above operations, the contents of the old structure storage area should be copied to the new storage area, including files_ Close contained in struct itself_ on_ exec,open_fds, fd to newly allocated close_on_exec,open_fds, copy of fd.
After executing the above copy, release the old struct fdtable,