Each process has a TASK_STRUCT structure in the Linux kernel that maintains process-related information, known as a process descriptor, and in the operating system theory, the Process Control block (pcb,process). There is a pointer in the task_struct (struct files_struct *files;) Point to the FILES_STRUCT structure, called the File descriptor table, where each of the entries contains a pointer to an open file, as shown in the following illustration.
The user program cannot directly access the file descriptor in the kernel, but only the index of the file descriptor (that is, 0, 1, 2, 3), which is called a file descriptor (descriptor) and is saved with an int variable. When the call to open opens a file or creates a new file, the kernel assigns a file descriptor and returns it to the user program that describes the pointer in the chart item to the newly opened file. When reading and writing a file, the user program passes the file descriptor to read or write, the kernel finds the corresponding table entry based on the file descriptor, and the corresponding file is found by the pointer in the table entry.
Open files are represented in the kernel by the file structure body, and the pointer in the file descriptor table points to the file structure body. Maintains the file Status Flag (member f_flags of the file structure) and the current read-write location (member F_pos of the file structure) in the file structure body. In the following illustration, Process 1 and Process 2 both open the same file, but correspond to different file structures, so you can have different file Status flag and read-write locations. The more important members of the file structure are also F_count, representing reference counts (Reference count), such as DUP, fork, and other system calls that cause multiple file descriptors to point to the same file structure, for example, FD1 and FD2 all refer to the same file structure body. Then its reference count is 2, when close (FD1) does not release the file structure, but only to reduce the reference count to 1, if the FD2, the reference count will be reduced to 0 also release the file structure, which really closed the files. Each file structure is directed to a file_operations structure, and the members of this structure are function pointers, which point to kernel functions that implement various file operations. For example, read a file descriptor in the user program, read through the system call into the kernel, and then find the file descriptor to point to the filename structure, find the file_operations structure of the document structure body, call its read member to point to the kernel function ( such as the implementation function in kernel code may be sys_read ()) to complete the user request. Call Lseek, read, write, IOCTL, open in the user program, and ultimately the kernel function that the core calls the File_operations member to complete the user request. The release member in the file_operations structure is used to complete the close request of the user program, which is called release rather than close because it does not necessarily shut down the file, but rather reduces the reference count, which closes the file only if the reference count is reduced to 0. For regular files that are open on the same file system, the steps and methods for file operations read, write, and so on should be the same, and the functions called should be the same, so the file structure of the three open files in the diagram points to the same file_operations structure body. If you open a character device file, its read,write operation must be different from the regular file, not read and write the disk data block but read and write the hardware device, so the file knotThe struct should point to a different file_operations structure, in which the various file manipulation functions are implemented by the driver of the device.