Reference: "Linux kernel design and implementation" 13th Chapter virtual file system
The virtual file system (VFS), as the kernel child operating system, provides a file and file system-related interface for user-space programs. Programs can use standard UNIX system calls (such as open (), read (), write ()) to read and write to different file systems, or even to file systems on different media. It is an abstraction layer, through the virtual interface to access the file system, it will be a variety of file system abstraction after the unified way to operate. VFS can converge on a wide variety of file systems because it defines the basic, conceptual interfaces, and data structures that all file systems support. At the same time, the actual file system also has its own concepts such as "How to open a file", "What is the directory" in the form of the definition of the VFS and consistency.
# #VFS对象及其数据结构
VFS uses object-oriented design ideas and uses a set of data structures to represent common file objects. Because the kernel is implemented purely with C code and does not use object-oriented language directly, the data structures in the kernel are implemented using the C language structure , which contains the function pointers that manipulate the data, and the operation functions are implemented by the specific file system. There are four main object types in the VFS. Each primary object contains an Action object that describes the methods that the kernel can use for the primary object. The action object is implemented as a struct pointer that contains a function pointer to the parent object of the action. For many of these methods, you can inherit the common functions provided by the VFS, and if the basic functionality provided by a common function does not meet your needs, then you must populate the function pointers with the unique methods of the actual file system to point to the file system instance. Four objects are associated with a pointer. Super Block (Super_block) object
The Super Block object represents a specific installed file system
All file systems must implement a super block object that is used to store information about a particular file system, typically a file system super block or file system control block that is stored in a specific sector of the disk. For file systems that are not disk-based (such as SYSFS), they create a super block using the field and save it in memory. The Super Block object is represented by the super_block structure and is defined in. The code that creates, manages, and revokes the Super Block object is in file FS/SUPER.C. Super Block objects are created and initialized by the Alloc_super () function. When the file system is installed, the file system calls the function to read the file system Super block from disk and populates its information in the memory of the Super Block object. Super Block Operation
The most important field in a Super Block object is S_op, which points to the table of operations functions for the Super block. The Super block action function table is represented by the super_operations structure and is defined in the file. Each item in the structure is a pointer to a Super block action function that performs low-level operations on file systems and index nodes. When the file system needs to perform operations on its Super block, first look for the desired action in the Super Block object. All action functions are called by the VFS in the context of the process. In addition to Dirty_inode (), other functions can be blocked if necessary. Some of these functions are optional. In the Super Block action table, the file system can set the unwanted function pointers to null. If the VFS discovers that the action function pointer is null, it either invokes the generic function to perform the appropriate action, or does nothing, and the choice depends on the specific operation. index Node (inode) object file
The Index node object represents a specific file
UNIX systems distinguish between the two concepts of file information and the file itself, such as access control permissions, size, owner, creation time, and so on. FILE-related information (also called metadata) is stored in a separate data structure called an index node.
The index node object contains all the information the kernel needs to manipulate the file or directory. For UNIX-style file systems, this information can be read directly from the Disk indexing node. If a filesystem does not have an index node, the file system must extract this information, regardless of how the information is stored on disk. File systems that do not have index nodes usually store the file's descriptive information as part of the file, and some modern file systems use the database to store the file's data. Either way, the indexed node object must be created in memory for the file system to use.
An index node object is represented by an inode structure, which is defined in a file. An index node represents a file in the file system (but the index node is created in memory only when the file is accessed), or it can be a special file such as a device or pipe. Therefore, there are some items in the index node structure that are related to special files, such as the I_pipe item, which points to a data structure representing a well-known pipe, I_bdev to the block device structure, and I_cdev to the character device structure. These three pointers are stored in a common body, because a given index node can only represent one of the three (or none of the three) at a time.
Sometimes, some file systems may not fully contain all the information required by the index node structure, at which point the file system can choose any appropriate solution in the implementation to solve the problem. Index node Operations
As with the Super block operation, the inode_operations entry in the indexed node object is also important because it describes all the methods that the VFS uses to manipulate the indexed node objects, which are implemented by the file system. Like a super block, the operation of an index node is invoked as follows:
I->i_op->truncate (i)
I point to the given index node, and the Truncate () function is defined by the file system where the index node I resides. The inode_operations structure is defined in a file. Catalog Item (dentry) object
VFS treats directories as files, but because VFS often needs to perform directory-related operations, pathname lookup needs to resolve each component of the path, not only to make sure it is valid, but also to look for the next part of the path further. To facilitate lookup operations, VFS introduces the concept of directory entries. Each dentry represents a specific part of the path. In the path (including the normal file), each section is a directory entry object. Parsing a path and traversing its component is by no means a simple walkthrough, which is a time-consuming, routine string-comparison process that is time-consuming to execute and cumbersome to code. The introduction of directory entry objects makes the process simpler. Directory entries can also include installation points. The VFS creates a directory entry object on site, if necessary, in the execution of directory operations.
The catalog item object is represented by the dentry structure and is defined in the file. Unlike the previous two objects, the directory entry object does not have a corresponding disk data structure, and VFS creates it based on the path name in the form of a string. And because the directory item object is not actually stored on disk, the directory item structure is not modified for Peugeot (whether dirty). Catalog Item Status
Directory entries have three valid states: used, unused, and negative.
A used directory entry corresponds to a valid index node (that is, D_inode points to the corresponding index node) and indicates that the object has one or more consumers (that is, D_count is positive). A directory entry card is used, meaning it is being used by VFS and points to valid data, so it cannot be discarded.
An unused directory entry corresponds to a valid index node, but it should be indicated that the VFS is not currently using it (D_count is 0). The directory item object still points to a valid object and is kept in the cache so that it can be reused when needed. Because the directory entry is not prematurely revoked, it is not necessary to re-create it later, as compared to an unassigned directory entry, which makes the path lookup faster. However, if you want to reclaim memory, you can undo unused directory entries.
A negative state directory entry does not have a valid index node (D_inode is null) because the index node has been deleted, or the path is no longer correct, but the directory entries remain so that the subsequent path queries are resolved quickly. Although a negative state directory entry is useful, it can be undone if necessary, because it is rarely used in practice.
When a catalog item object is released, it can also be saved to the Slab object cache, at which point any VFS or file system code does not have a valid reference to the directory object. Directory Item Caching
If the VFS layer traverses all the elements in the pathname and parses them into the directory item object one at a time, it will be a very laborious task, and it will be a waste to the master. So the kernel caches directory item objects in the directory item cache (Dcache).
The directory entry cache includes three main sections: the "used" catalog necklace table. The linked list connects the associated index nodes through the I_dentry entry in the indexed node object, because a given index node may have multiple links, so there may be multiple directory item objects, so a linked list is used to connect them. "Recently used" doubly linked list. The list contains a directory entry object that is not in use and is in a negative state. The linked list always inserts a table of contents entry in the header, so the data for the chain head node is always newer than the data at the end of the chain. When the kernel must reclaim memory by deleting a node item, the node (oldest) is deleted from the end of the chain. The hash table and the corresponding hash function are used to quickly resolve a given path to a related directory entry object. A hash table is represented by an array dentry_hashtable, where each element is a pointer to a list of catalog item objects that have the same key value. The size of the array depends on the size of the physical memory in the system. The actual hash value is computed by the D_hash () function, which is the only hash function that the kernel provides to the file system. Find a hash list to pass the D_lookup () function, the matching object is returned if the function finds a matching directory entry object in Dcache, otherwise a null pointer is returned.
Dcache also provides caching of index nodes in a sense, that is, Icache. The index node object associated with the directory entry object will not be freed because the catalog entry will allow the associated index node to count as positive, thus ensuring that the index node remains in memory. The corresponding index nodes are cached as long as the directory entries are cached. Catalog Item Actions
Dentry_operation constructs all the methods of the VFS operation directory entry. The structure is defined in a file. See p224 file Object in detail
A file object represents a file that has been opened by the process, and the object (not a physical file) is created by the corresponding open () system call, revoked by the close () system call, and all of these file-related calls are actually methods defined in the File action table. Because multiple processes can open and manipulate the same file at the same time, multiple corresponding file objects may exist for the same file. The file object represents the open file only in the process view, which in turn points to the Directory item object (which in turn points to the index node), but only the Catalog item object represents the actual file that is actually open. Although a file's corresponding file object is not unique, the corresponding index node and directory object are undoubtedly unique.
The file object is represented by the filename structure and is defined in. Similar to the directory entry object, the file object does not actually have the corresponding disk data. Therefore, there is no flag in the structure that represents whether the object is dirty or if it needs to be written back to disk. The file object points to the related directory entry object through the F_dentry pointer. The directory entry points to the associated index node, and the index node records whether the file is dirty. File Actions
The operations associated with the file structure are similar to system calls, which are the basis for standard UNIX system calls. The operation of the file object is represented by the file_operations structure and is defined in the file. Specific file systems can be implemented specifically for each operation, or generic operations can be used if there is a common operation.
About IOCTLs
There are now three ways of IOCTL. Unlocked_ioctl () and IOCTL are the same, although they are invoked without a large kernel lock (BKL). Therefore, the author of the function must ensure proper synchronization. Because a large kernel lock is a coarse-grained, inefficient lock, the driver should implement UNLOCKED_IOCTL () instead of IOCTL ().
Compat_ioctl () is also invoked without a large kernel lock, but its purpose is to provide a 32-bit IOCTL compatibility method for 64-bit systems. How you implement it depends on the existing IOCTL command. Early drivers implicitly have a size-determining type (such as long) and should implement the Compat_ioctl () method for 32-bit applications. This usually means converting the 32-bit value to the appropriate type in the 64-bit kernel. New driver Redesign IOCTL command, it is safe to run a 32-bit application on a 32-bit system, and it is safe to run 32-bit applications on a 64-bit system, and it is safe to run 64-bit applications on a 64-bit system, to ensure that all parameters and data have a clear size data type. These drivers allow the COMPAT_IOCTL () function pointer and the UNLOCKED_IOCTL () function pointer to point to the same function. data structure related to file system
In addition to the above several VFS base objects, the kernel uses other standard data structures to manage other related data of the file system. The first object is File_system_type, which describes a variety of specific file system types. The second structure is Vfsmount, which describes an instance of an installation file system.
Because Linux supports many different file systems, the kernel must have a special structure to describe the functionality and behavior of each file system. The FILE_SYSTEM_TYPE structure is defined in. Each file system has only one file_system_type structure, regardless of how many instances are actually installed in the system or are not installed in the system at all. When the file system is actually installed, a VFSMOUNT structure is created at the installation point. The structure is used to represent instances of the file system. The VFSMOUNT structure is defined in. Clearing the relationship between the file system and all other installation points is the most complex task in maintaining all the installation point lists. So the various linked lists maintained in the VFSMOUNT structure are designed to be able to track these associated information. The Vfsmount structure also holds the flag information specified at installation time, which is stored in the mnt_flages domain. As shown in the following table:
| Sign |
Describe |
| Mnt_nosuid |
Disable executable files for this file system to set setuid and Setgid flags |
| Mnt_modev |
Prohibit access to device files on this file system |
| Mnt_noexec |
Prohibit execution of executable files on this file system |
These flags are useful when installing mobile devices that are not fully trusted by administrators. They are defined in with some of the other rarely used flags. and process-related data structures
Each process in the system has its own set of open files, such as the root file system, the current working directory, the installation point, and so on. There are three data structures that are closely related to the process of the VFS layer and the system, respectively: File_struct, Fs_struct, and namespace structures.
The FILE_STRUCT structure is defined in a file that is pointed to by the Files directory entry in the process descriptor. All information related to a single process (per-process), such as open files and file descriptors, is included.
The FS_STRUCT structure is pointed to by the FS field of the process descriptor. It contains information related to the process and is defined in the file. The structure contains the current working directory (PWD) and root directory of the current process.
The namespace structure is defined in a file and is pointed to by the Mmt_namespace field in the process descriptor. After the 2.4 kernel, the single process namespace is added to the kernel, and it is reluctant to see each process seeing a unique installation file system in the system-not only the unique root directory, but also the unique file system hierarchy.
The
Above data structures are all connected through a process descriptor. For most processes, their descriptors point to a unique files_struct and fs_struct structure. However, for those processes created using the clone flags Clone_files or CLONE_FS, the two structures are shared. Therefore, multiple process descriptors may point to the same files_struct or fs_struct struct body. Each structure maintains a count field as a reference count, which prevents the struct from being revoked when the process is using it. &NBSP
Namespace structures are used in a way that is completely different from the first two, by default, all processes share the same namespaces (that is, they all see the same file system hierarchy from the same Mount table). A copy of a unique namespace structure is given to a process only if the CLONE_NEWS flag is used for the clone () operation. Because most processes do not provide this flag, all processes inherit the namespace of their parent process. Therefore, there is only one namespace on most systems, but the CLONE_NEWS flag can invalidate this functionality.