目录
2.1.从源码的角度理解,文件流指针(struct _IO_FILE)是什么编辑
一、文件描述符
文件描述符:文件描述符就是一个小正数
1.1文件描述符的分配规则
我们可以通过写代码来进行测试
我们首先要知道的是一个进程在创建的过程中就会打开三个文件 标准输入,标准输出,标准错误
我们这时候直接打开两个文件,看看获得的两个文件描述符分别是什么
可以看到两个文件描述符是3和4
我们写了一个代码,在开始的时候先把0号和2号文件给关闭了,这时候再去打开两个文件,
去观察两个文件的文件描述符是多少
我们可以看到,新打开的文件占据了原来的0号2号,在结合之前的结果可以得出结论
结论:文件描述符的分配原则是最小未使用原则
1.2从内核角度理解文件描述符
1、从task_struct 的角度理解文件描述符在内核当中是什么
文件是在进程当中打开的,所以文件描述符一定脱离不了进程这个范畴
在(进程)struct task_struct{...}中,有个结构体指针,指向了一个叫struct files_struct的结构体,
而这个结构体里面又又一个struct file*的结构体指针数组,这个数组里面存储的指针又指向了一个个的结构体,指向的结构体是用来保存文件信息的,其中有一个信息是这个文件在磁盘中存储的位置,(平时使用文件的时候也是通过这个信息去在磁盘中找到这个文件去进行使用的)。
那么进程描述符在这张图里面是什么呢?
进程描述符就是struct file*[ ]这个数组的下标。
我们通过open打开一个文件的时候,这时候返回的文件描述符的值是3,这个过程其实就是struct file* [ ]这个数组向后开辟了一个数组单位,而文件描述符恰好就是这个数组的下标
我们平时在知道了一个文件的文件描述符的时候,其实通过进行寻找,就能找到文件的信息
二、理解文件描述符和文件流指针的区别
2.1.从源码的角度理解,文件流指针(struct _IO_FILE)是什么
可以看到,在源码中,struct _ IO FILE 被重命名为了FILE,也就是说FILE其实是一个结构体,那么我们就来了解一下这个结构体
先来试一下用struct _IO FILE代替FILE
可以看到确实是和FILE的功能一模一样,而且我们使用了fp->_fileno去查看了文件描述符,可以证明文件描述符是包含在文件流指针当中的
2.2接下来来深入了解一下这个结构体
这个结构体内部包含有 读缓冲区、写缓冲区、 int _fileno 这三个部分
而这里的缓冲区就和之前学的刷新缓冲区是一个东西,
2.3对于之前的exit和_exit函数就有了更深的理解
1、直接调用_exit是不会刷新缓冲区的,是因为操作系统内核压根就不知道缓冲区的存在,都不知这的存在自然不能刷新缓冲区
2、而调用exit的时候会刷新缓冲区是因为这个缓冲区本来就是属于C库的,这当然就能知道缓冲区的存在
这里的 int _fileno保存文件描述符的数组则又和文件描述符联系在一起的
所以 文件流指针到底是什么?
就是一个结构体
三、重定向
3.1重定向的符号
- > :清空重定向
我们现在1.txt文件当中写入一些代码:
然后在使用 >这个命令
可以发现,先将原来文件内容清空之后再重定向新的内容
- >> :追加重定向
3.2从内核角度理解重定向
重定向的本质就是将结构体指针的指向给改变了
对于peintf来说,他的结构体指针原本指向输出文件,但如果使用命令指向我们写的1.txt文件以后,那么使用peintf就不会在输出数据,而是将内容写入了我们的1.txt文件】
-
3.3重定向的接口
- int dup2(int oldfd, int newfd);
- 作用:将newfd的值重定向为oldfd,即newfd拷贝oldfd
- 参数: oldfd/ newfd均是文件描述符
- 成功:
- 1.关闭newfd
- 2.让newfd指向oldfd对应的struct file*结构体
- 失败:
- 1.如果oldfd是个非法/ 无效的文件描述符, 则重定向失败; newfd没有 变化
- 2.如果o ldf d和newf d的值相等,则什么 事情都不干
代码验证:
将标准输出中的内容重定向为1.txt文件
可以发现,并没有输出”after dup2.。。。”,而是将这个内容重定向进入了1.txt文件
最后在通过查看磁盘中文件的软连接关系可以看到1号文件描述符被重定向到1.txt文件结构体
所以,重定向成功。