Linux uses a tree structure to organize management files. The top of the tree is the root directory (/), the nodes are directories, and the leaves at the end are files containing data. When given the full path to a file, we start from the root directory and travel through various directories along the way to the file.
We can perform many operations on files, such as opening and reading and writing. In Linux file management related commands, we see many commands that operate on files. They are mostly based on opening and reading files. For example, CAT can open a file, read data, and display it on the terminal:
$cat test.txtCopy the code
For Linux programmers, understanding the underlying organization of the file system is essential for further system programming. Even ordinary Linux users can design better system maintenance schemes based on relevant contents.
The ultimate purpose of a file system is to organize large amounts of data into storage devices that persist, such as hard disks and disks. These storage devices are different from memory. Their storage capacity is durable and does not disappear because of power outages; Large storage capacity, but slow reading speed.
Observe common storage devices. The initial area is the MBR for Linux boot (see Linux Boot). The remaining space may be divided into several partitions. Each Partition has an associated Partition table, which records information about partitions. The partition table is stored outside the partition. The partition table describes the starting location and size of the corresponding partition.
We often see C partitions, D partitions, and so on in Windows systems. On Linux, you can have multiple partitions, but they are all mounted on the same filesystem tree.
Data is stored in a partition. A typical Linux partition contains the following parts:
The first part of a partition is a Boot block, which is used to Boot up the computer. When Linux starts up, it loads the MBR first, and then the MBR loads programs from the boot area of a hard disk. This program is responsible for further operating system loading and startup. To facilitate management, Linux reserves a boot zone for a partition even if no operating system is installed in the partition.
After the boot zone comes the Super Block. It stores information about the file system, including the type of file system, the number of inodes, and the number of data blocks.
Then there are the multiple inodes, which are key to implementing file storage. In Linux, a file can be stored in chunks, like a dragon ball scattered around. In order to successfully collect dragon balls, we need a “radar” guide: the inode corresponding to the file. Each file corresponds to one inode. This inode contains Pointers to individual blocks of data belonging to the file. When the operating system needs to read the file, all it needs is the “map” of the inode to collect the scattered blocks of data and harvest our file.
Finally, there are the data blocks that actually store the data.
Above we have seen the macro structure of the storage device. We’ll delve into the structure of partitions, especially the way files are stored in partitions.
A file is a partition unit of data by a file system. File systems use directories to organize files, giving files a hierarchical structure. The key to implementing this hierarchical structure on hard disk is the use of inodes to virtualize normal and directory file objects.
In Linux file management, we know that in addition to its own data, a file has an additional information, namely the file’s metadata. This metadata is used to record a lot of information about a file, such as file size, owner, group to which it belongs, modification date, and so on. Metadata is not contained in the file’s data, but is maintained by the operating system. In fact, this so-called metadata is contained in the inode. We can view this metadata with $ls -l filename. As we saw above, the inode occupies a different region than the data block. Each inode is represented by a unique integer inode number.
In saving metadata, inodes are the key to “files” from abstract to concrete. As mentioned in the previous section, inodes are stored by Pointers to blocks of data on a storage device where the contents of a file are stored. When Linux wants to open a file, it simply finds the file’s inode and collects all the data blocks along the pointer to form the file’s data in memory.
Inodes are not the only way to organize files. The easiest way to organize files is to put them sequentially on a storage device. DVDS take a similar approach. However, if there is deletion operation, the free space caused by deletion is mixed in the normal files, which is difficult to use and manage.
The more complex approach is to use linked lists, where each block of data has a pointer to the next block of data belonging to the same file. The advantage of this is that you can take advantage of the scattered free space, but the disadvantage is that you have to operate on files in a linear fashion. If you want random access, you must traverse the list all the way to the destination. Since this traversal is not in memory, it is slow.
The FAT system takes the pointer to the above list and puts it into an array in memory. In this way, FAT can quickly find a file based on the memory index. The main problem with this is that the size of the indexed array is the same as the total number of data blocks. Therefore, if the storage device is large, the index array will be large.
Inodes solve this problem by making full use of space and taking up space in memory independently of the storage device. But inode has its own problems. The total number of Pointers to data blocks that each inode can store is fixed. If a file needs more blocks than that, the inode needs extra space to store the extra Pointers.
In Linux, we parse the path to find a file based on directory files along the way. Entries in directories have inode numbers in addition to the file names they contain. When we type $cat /var/test.txt, Linux will find the var inode number in the root directory file and synthesize the var data from the inode. Then, according to the records in var, find the inode number of text.txt, and collect data blocks along the pointer in inode to synthesize text.txt data. In the whole process, we refer to three inodes: the root directory file, the var directory file, and the inodes of the text.txt file.
In Linux, you can use $stat filename to query the inode number of a file.
In the storage device, it is actually stored as:
When we read a file, we actually find the file’s inode number in the directory, and then combine the blocks according to the inode pointer and put them into memory for further processing. When we write to a file, we allocate a blank inode to the file, enter its inode number into the directory that the file belongs to, and then select blank blocks of data. The inode pointer refers to these blocks and puts the data into memory.
In the Linux process, when we open a file, we return a file descriptor. The file descriptor is the subscript of an array whose element is a pointer. Interestingly, this pointer does not point directly to the file’s inode, but rather to a table of files that, in turn, points to the inode of the target file loaded into memory. As shown below, a process has two files open.
As you can see, each file table records the status flags of the open file, such as read only, write, etc., as well as the current read/write position of each file. When two processes open the same file, there can be two file tables, each corresponding open state and the current position of the file table, to support some file sharing operations, such as simultaneous reading.
Note that after the process fork, the child will only copy the array of file descriptors and share the kernel-maintained file tables and inodes with the parent. Be especially careful with your programming at this point.
The original link: http://www.cnblogs.com/vamei