目录
前文
一,为什么有文件描述符
二,什么是文件描述符
2.1 文件操作接口
2.2 文件描述符
三,文件描述符的原理
四,文件描述符的分配规则
前文
本文主要是详解一下文件描述符,我们从1.为什么?2.是什么?3.实现原理三个方面来解释。
一,为什么有文件描述符
在语言和系统的学习中,IO流的学习是绕不开的,在其中我们会学到文件的打开,关闭,读取,写入等操作,而在这里面当文件被系统打开后,要怎么管理这些打开的文件呢?这时候就需要用到文件描述符来管理这些被打开的文件。
二,什么是文件描述符
2.1 文件操作接口
首先在C语言的库中有一系列的文件操作函数,如fopen(打开),fclose(关闭),fputs(写入),fgets(读取),众所周知语言层面的库是通过封装操作系统提供的接口来完成底层硬件的操作,而C语言的文件操作函数也不例外,其对应的底层接口分别是open(打开),close(关闭),write(写入),read(读取)
2.2 文件描述符
细心的同学一个已经放下,在上面的系统接口中,我用红线将变量fd标注出来,其实这就是文件描述符,在我们调用open打开文件或者新建文件后,系统会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
文件描述符在形式上是一个非负整数。实际上,它是一个数组下标,指向系统为每一个进程所维护的该进程打开文件的文件描述符表。
接下来我们来写一个简单的代码来观察一下文件描述符:
这里我们发现我们只开了一个文件,但是文件操作符却是3,而不是0,1,2,这是为什么呢? 首先在Linux中我们要理解一切皆文件的第一要义,而从键盘输入,从显示器输出,其实也是打开对应的设备文件进行输入输出,即stdin,stdout,以及错误输出stderr,这三个分别称为标准输入,标准输出,标准错误,这三个默认的文件操作符分别是0,1,2。
三,文件描述符的原理
首先用户创建一个进程,我们创建一个进程结构task_struct来表示进程的属性,其中有一个File指针指向files_struct,其中存储这文件描述符表arr[],当我们打开文件时,会在内存中创建一个file_struct来存储每个打开文件的属性,然后这些file_struct按照文件描述符的规则再一一映射到文件描述符表arr[]中,因此当我们想修改或者读取log.txt文件时,就是通过log.txt的文件描述符在文件描述符表arr[]中找到其对应的file_struct结构体指针,然后对文件进行访问。
四,文件描述符的分配规则
规则:在file_struct中从小到大找到找到一个没有被使用的下标,作为新的文件描述符。
我们可以写一段代码来证明一下。
观察上图我们发现,当我们关闭0也就是stdin文件时,新开文件的文件描述符会从0下标开始