[Linux] Talking about file descriptors and redirection

foreword

The file descriptor is an integer that grows from 0. For a Linux process, three file descriptors 0, 1, and 2 are opened by default, that is, three files are opened.

file descriptor document
0 standard input keyboard file
1 stdout monitor file
2 standard errors monitor file

When we open a new file with the system interface open, the newly allocated file descriptor is the 最小的未被分配的
directory

1. Processes, files and file descriptors

We must first clarify such a concept: when the file is located on the disk, when we want to operate the file, we actually create a process to operate the file

In the structure corresponding to the process control block pcb task_struct, we can find a files_structpointer to a structure files, and the process uses this structure to manage the files it opens.
insert image description here
Go to definition:
insert image description here
When you mention integers starting from 0, what do you think of?

Array subscripts!

We found that files_structthere is exactly an fd_arrayarray called struct file*, and when we look at the struct file structure, it is the structure that describes the properties and methods of the file:
insert image description here
among them, struct file_operationsmethods such as read and write are defined:
insert image description here
we can see, Function pointers are the way C language structures implement object-oriented


It is also worth mentioning that for all files, whether it is a display file, a keyboard file, or a normal file, the function pointer method provided in the file_operations in the file structure looks the same

Some people may ask, the method of reading a keyboard file and opening a network card file must be different. How to call it is called read

In fact, after calling read, read will go to the lower layer to call the read method provided by the specific file. For the network card, it is the network card driver, and the driver contains the read method of the specific network card.

In this way, at the operating system level, the reading of all files is abstracted at the OS layer read, and the operating system reads all files at the OS layer. The read in file_operations is used.

In the form of function pointers, the underlying layer and virtualization are shielded from differences in underlying hardware. Function pointers point to different underlying methods, so that the upper layer can view files from the same perspective, and abstract the commonality of each hardware for the operating system to use functions directly. Pointer calling method to complete the feature of everything is a file


In summary, the file descriptor is the subscript of the array fd_array, and each array member points to the attribute structure of a file to manage a specific file

Linux abstracts the files opened by the process into file descriptors such as 0, 1, 2, etc., and manages the files by means of arrays and array subscripts

Only one picture covers it:
insert image description here

2. Redirect

Since a process can find a specific file according to the file descriptor, can it be changed as long as we modify the corresponding relationship between the file descriptor and the file?

Of course!

We know that printf in C language is to print to the display, then at the system layer, printf must write to the file whose file descriptor is 1

printf always thinks that the file with fd == 1 is a display file, yes, it is right, it does not care what file fd == 1 points to.

So, according to one of our rules above:

The newly allocated file descriptor is the smallest unallocated

Then if we close file descriptor 1 first, which is standard input

Then create and open a normal file file.txt, the file descriptor assigned to file.txt should be 1

Then call printf("hello world")

So is helloworld printed on the screen, or written to file.txt?

#include <stdio.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
#include <unistd.h>    
int main() {
    
        
// 关闭1号文件描述符
  close(1); 
// 写的方式打开file.txt
  int fd = open("file.txt", O_WRONLY|O_CREAT, 0644);    
// 向1号文件描述符写入
  printf("helloworld\n");     
// 刷新缓冲区                                                          
  fflush(stdout);
// 关闭文件描述符    
  close(fd);    
  return 0;    
}    

It turns out that helloworld is written to file.txt:

insert image description here
what is this?

Heavy! Certainly! Towards!

Guess you like

Origin blog.csdn.net/m0_52640673/article/details/123157059