wx:嵌入式工程师成长日记
在Linux操作系统中的一切都被抽象成了文件,当在进程中打开一个现有文件或者创建一个新文件时,内核向该进程返回一个文件描述符,用于对应这个打开/新建的文件。这些文件描述符都存储在内核为每个进程维护的一个文件描述符表中。
int fd1 = open("log1.txt", O_WRONLY|O_CREAT|O_APPEND, 0666); //rw-rw-rw-
int fd2 = open("log2.txt", O_WRONLY|O_CREAT|O_APPEND, 0666); //rw-rw-rw-
当我们运行程序时,系统会默认帮我们打开标准输入、标准输出、标准错误。
-
标准输入(STDIN_FILENO):默认为 0,代表程序的标准输入流。
-
标准输出(STDOUT_FILENO):默认为 1,代表程序的标准输出流。
-
标准错误(STDERR_FILENO):默认为 2,代表程序的标准错误输出流。
文件描述符表
启动一个进程就会得到一个对应的虚拟地址空间,这个虚拟地址空间分为两大部分,在内核区有专门用于进程管理的模块。Linux的进程控制块(PCB),本质是一个叫做task_struct的结构体,里边包括管理进程所需的各种信息,其中有一个结构体叫做file ,我们将它叫做文件描述符表,里边有一个整形索引表,用于存储文件描述符。
内核为每一个进程维护了一个文件描述符表,索引表中的值都是从0开始的,所以在不同的进程中可以看到相同的文件描述符,但是它们指向的不一定是同一个磁盘文件。
当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件,于是就有了file结构体,表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。
每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包含一个指针数组,每个元素都是一个指向打开文件的指针。
所以,文件描述符就是该数组的下标。只要有文件描述符,就可以找到对应的文件。
小知识点:
①每一个进程对应的文件描述符表能够存储的打开的文件数是有限制的, 默认为1024个。
②一个进程中不同的文件描述符打开的磁盘文件可能是同一个。
③每个进程的文件描述符表中都已经默认分配了三个文件描述符,对应的都是当前终端文件(/dev/tty)。
④每打开新的文件,内核会从进程的文件描述符表中找到一个空闲的没有别占用的文件描述符与其进行关联。
⑤每个进程文件描述符表中的文件描述符值是唯一的,不会重复。