当前位置:主页 > 查看内容

Linux——基础IO(二):文件描述符,文件流指针,重定向

发布时间:2021-05-21 00:00| 位朋友查看

简介:文章目录 1. 文件描述符 1.1 文件描述符的实质 1.2 文件描述符的分配规则 1.3 一个进程最大可以开多少个文件描述符 2. 文件流指针(FILE) 2.1 前言 2.2 文件流指针的本质 2.3 深究FILE 3. 文件流指针和文件描述符的区别 4. 重定向 4.1 重定向的命令符号 4.2……


1. 文件描述符

文件描述符就是内核当中 fd_array 数组的下标,是一个正整数

我们写出如下代码,并在代码最后加上一个循环,让代码不要退出
在这里插入图片描述
运行程序,后查看当前进程
在这里插入图片描述
如下图所示:

文件描述符:

  • 0–>标准输入
  • 1–>标准输出
  • 2–>标准错误
    在这里插入图片描述

1.1 文件描述符的实质:

在进程中有一个结构体指针(struct file_struct* files),指向了一个结构体(struct files_struct),而在这个结构体(struct files_struct)中有一个数组,这个数组的下标就是文件描述符,数组的每个元素的类型是struct file*,struct file* 这个结构体指针指向 struct file这个结构体(保存了文件的元信息),而最终和磁盘打交道的就是struct file这个结构体
在这里插入图片描述

1.2 文件描述符的分配规则:

最小占用原则:在数组中找到当前没有被使用的最小的一个下标,作为新的文件描述符

如下代码所示,我们关闭了2,会发现fd不是3而是2
在这里插入图片描述
在这里插入图片描述

1.3 一个进程最大可以开多少个文件描述符?

进程最大打开文件描述符个数是由操作系统中一个参数限制的,可以通过命令:ulimit -a查看到一个open files,open files后面的值就是进程可以打开的最大文件描述符个数

在这里插入图片描述

最大文件描述符个数更改:ulimit -n

2. 文件流指针(FILE)

2.1 前言

我们可以先cd到 /usr/include目录下,在此目录下我们可以看到所有的头文件
在这里插入图片描述
我们在用vim打开stdio.h
在这里插入图片描述
此时我们就可以找到FILE
在这里插入图片描述

2.2 文件流指针的本质

  • FILE文件流指针是一个typedef之后的值,本质是一个结构体
  • 在“/usr/include/stdio.h”目录下可以看到

2.3 深究FILE

而我们怎么才能查看FILE这个结构体中的内容呢?

我们可以通过grep "struct _IO_FILE {" . -R命令进行搜索,此时我们会看到,这个结构体的位置在 ./libio.h
在这里插入图片描述
此时我们只需vim进入libio.h,在进行搜索即可找到
在这里插入图片描述
在struct _IO_FILE这个结构体中,我们可以看到读缓冲区写缓冲区
在这里插入图片描述
int _fileno;当中保存的内容就是文件描述符
在这里插入图片描述
在此我们可以更清楚的了解文件流指针的工作原理,如下图所示:
在这里插入图片描述

?????之前在进程终止的时候说的刷新缓冲区:指的是C库当中维护的读写缓冲区
?????借助上图我们可以理解:_exit()函数之所以不会刷新缓冲区,是因为_exit()函数是内核代码,直接操作内核结束结束了进程,而此时并不会通知上层的C库,所以,C库维护的缓冲区完全在无感知的情况下进程就终结了

3. 文件流指针和文件描述符的区别

  • 文件流指针是一个结构体,在结构体内部保存了文件描述符
    ?
  • 文件描述符是一个正整数,其含义为fd_array数组的下标
    ?
  • 文件流指针维护了读写缓冲区

4. 重定向

4.1 重定向的命令符号

?> :清空重定向,将文件内容清空之后在重定向

测试如下:

我们vim一个abc文件,可以看到abc文件中的内容如下图所示:
在这里插入图片描述
然后我们使用 ls > abc 命令之后可以看到abc中的内容已经被清空重定向了
在这里插入图片描述

?>> :追加重定向,直接在文件的尾部进行重定向

测试如下:
我们对abc文件进行追加重定向,可以看到,直接在文件的尾巴进行了重定向
在这里插入图片描述

4.2 重定向的原理

将 fd_array 数组当中的元素struct file* 指针的指向关系进行修改,改变成为其它的struct file结构体的地址

在这里插入图片描述

4.3 使用dup2系统调用

int dup2(int oldfd, int newfd);

通过man手册我们可以对dup2函数进行一些了解,我们会看到这样一段话
在这里插入图片描述

  • newfd的值是拷贝于oldfd的值,及newfd的值来源于oldfd
    ?
    eg:上文重定向原理图解中的过程可以写为:dup2(3,0);

在这里插入图片描述

(1) 如果必要,使用dup2进行重定向的时候,会先关闭newfd
?

  • 必要:oldfd是正常的文件描述符
    ?
  • 如果oldfd不是一个有效的文件描述符,则不关闭newfd,重定向失败 eg:dup2(10,0) 没有文件描述符10
    ?
  • 如果oldfd是一个有效的文件描述符并且和newfd是相同的文件描述符数值,则dup2什么事情都不有干 eg:dup2(0,0);

(2) 将oldfd的值拷贝给newfd

注意:
? ? ? 一般C库函数写入文件时是全缓冲,而写入显示器是行缓存

? ? ? eg:“\n”==》行缓冲

;原文链接:https://blog.csdn.net/weixin_50886514/article/details/115480352
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐