文章目录
本作者从代码及源码的角度来总结探究文件描述符fd
参考:韦东山Linux嵌入式视频
文件描述符
Linux系统下一切皆文件。文件描述符是操作系统中用来唯一标识一个已打开文件的整数。本质上来说就是索引,即根据索引值寻找到对应的文件,可对其进行相应的操作。
使用open函数打开文件得到一个文件描述符,然后使用read和write函数通过文件描述符进行读写操作。所有执行I/O操作的系统调用都通过文件描述符来实现。
首先,创建一个test.c文件
vim test.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if(argc != 2){
printf("Usage:%s <file>\n",argv[0]);
return -1;
}
int fd = open(argv[1], O_RDONLY);
printf("fd = %d\n",fd);
while(1){
sleep(100);
}
return 0;
}
编译,且运行打开test.c文件,&:表示后台运行,产生一个进程17985,打印文件描述符fd=3。
gcc -o test test.c
/test test.c &
ps查看后台进程资源运行情况,切换到proc虚拟文件系统查看进程信息,进入fd目录查看对应文件描述符fd=3指向的就是打开test.c。其中fd=0,1,2分别对应标准输入、标准输出、标准错误
内核源码:
- open函数的系统调用会进入内核调用内核函数,一个进程就会产生
struct task_struct
结构体。** task_struct**结构体用于管理进程,包含了一个进程所需的所有信息。这也是PCB(进程控制块) - task_struct结构体的成员变量含有
struct files_struct *files
结构体,files_struct结构体管理进程打开的所有文件的管理结构。 - files_struct结构体的成员变量含有
struct fdtable fdtab
结构体,fdtable结构体管理进程的文件描述符表。 - fdtable结构体的成员变量含有
struct file __rcu **fd
结构体,file结构体表示一个打开的文件,并且包含了许多与文件操作相关的信息和属性
即:struct task_struct—>struct files_struct *files—>struct fdtable *fdt—>struct file **fd。
特别的,
struct file __rcu **fd; /* current fd array */
fd是一个二级指针,指向的类型是是struct file
类型的指针,指向的地址存储的是strcut file类型的元素,地址里的元素strcut file指向的是struct file
fd.table.fd指向一个数组,数组元素为指针,指针类型为srtuct file *。
其中fd为一个数组,表中的元素为文件描述符(本质是索引或标识符)
0 :STDIN_FILENO 接收键盘的输入
1 :STDOUT_FILENO 向屏幕输出
2 :STDERR_FILENO 标准错误
3:上图打开的test.c文件
而这些又分别指向自己的struct file结构体,而这个结构体存放着该文件的一些重要信息
关系如下所示