个人主页:Lei宝啊?
愿所有美好如期而遇
我们介绍文件描述符的顺序是:
我们就很疑惑,0,1,2哪里去了,为什么fd是从3开始的?
这里我们就要先了解FILE*类型,首先,我们要知道FILE是一个结构体,由C标准库所支持,并且,由此支持了FILE*类型的stdin(标准输入),stdout(标准输出),stderr(标准错误),分别对应着键盘,显示器,显示器。
我们在使用fwrite或者时fputs等文件类函数时,参数通常会有stdin,stdout,我们也应该知道,这些函数他既然能够访问硬件,那么就一定封装了系统调用,就比如fwrite封装了write,fputs封装了read,fopen封装了open,fclose封装了close。
C标准库支持的文件类函数认识FILE*,但我们的系统调用他只认识fd,并不认识FILE*,所以我们上层传入的FILE里必然封装了fd,并且在底层以FILE*->fd的方式传递给了系统调用。(我们使用fopen打开文件,返回值是FILE*类型,fopen的底层封装了open,open的返回值是fd,所以我们也就知道了FILE*类型是封装了fd的,以后其他文件类函数使用时传入FILE*底层就可以得到fd了)
那么现在我们可以揭晓答案了,stdin里封装的fd为0,stdout里封装的fd为1,stderr里封装的fd为2,进程跑起来时这三个文件是被默认打开的,所以我们再打开其他文件,fd就从3开始了。
那么fd是什么呢?
我们从头开始理解,当我们运行一个程序,想让一个进程去访问文件时,如何访问文件?首先是不是应该让文件从磁盘加载进内存中,因为根据冯诺依曼体系,一个文件要被访问执行,首先要加载进内存,然后由CPU去计算执行,那么我们的进程访问文件,只能访问一个吗?当然不是,刚才我们同时打开了多个文件,一个进程默认情况下可以打开1024个文件,那么我们多个进程同时打开多个文件是不是也可以?那么这么多的进程和文件在内存中,进程需要被操作系统管理,文件需不需要?当然需要,怎么管理?同进程一样,先描述,再组织。
也就是说,我们可以通过task_struct中arrry数组,找到所有打开的文件,现在,我们终于可以明白fd本质就是数组下标!它叫做文件描述符。
现在我们重新理解思路,当一个文件打开时,会在内存中创建struct file(包含了磁盘文件的几乎所有内容),之后将他的地址填入数组,给用户(或者说open函数)返回填入位置的下标,当我们想要找到打开的文件时,通过返回的fd就可以找到struct file,而这个结构体几乎包含了文件的所有信息!我们也就能够通过这个结构体访问这个文件,对文件进行一系列操作。
接下来我们验证FILE*对fd的封装