当前位置: 首页 > article >正文

fd,重定向与缓冲区

目录

理解一切皆文件

IO的基本过程

重定向

dup2重定向


ls /dev/pts指令用于查询服务器下面的终端,开了几个服务器界面就会有几个终端,而 ptmx 是伪终端主设备(pseudoterminal master)这个不算。

可以从一个终端向另一个中端写入数据。

我们从shell的文件可以打开终端,所以终端又是属于文件的。这也映照了Linux下一切接文件。

每个打开的文件在内核当中都有file对象,保存了文件的inode元素信息。

理解一切皆文件

所有的外设都是文件没问题吧,所以外设都是内容+属性,在属于自己的属性结构体里面保存着信息,今天一个进程通过通过文件描述符表的指针直接调用read或者write函数指针读取所对应fd的文件,那这么多的文件难道需要n多个写或者读函数吗,说明这些read/write函数都是一样的,一样的调用下层的文件属性结构体,那读操作的上层,操作系统另外封装了一层软件层,c语言的底层封装了操作系统的文件操作,所以最上层是glibc(C语言标准库),然后再聊read指针,这么多相同的read指针,进行读取不同的文件,同一个东西可以有不同的状态或者效果,着不就是类似于多态的东西吗,这就是虚拟文件系统,同样的先描述再组织的原则,虽然IO/read/write属性和类别一样但是值可以不同,IO方法又是不同的。

为什么语言喜欢做封装呀,在操作系统都文件函数中如果要以二进制写入数字的话是不行的,这样是会乱码的,所以被剖snprintf转成字符串数组,不同的类型要做不同的转换,在语言层面就没有这个问题,void* 就包含了所有类型了,所以语言喜欢做封装1是方便用户操作,语言封装了才可以在操作系统上进行调用,无论哪种操作系统都是需要兼容语言的,所以2是为了提高语言的可植入性!

IO的基本过程

文件读写过程存在文件内核缓冲区,进程通过struct file的指针找到文件输入或者输出,每个文件都配有操作表,属性集,内核缓冲区,写入文件时会先写入缓冲区,等文件的缓冲区差不多了的时候再一次性写入文件,这个写入文件的过程由OS决定的,修改的本质是先从文件中读取,修改再写入,有时候就需要在文件缓冲区中读取,为什么要有文件缓冲区,统一写入肯定比边输入边就写入快,因为外设比较慢,而输入CPU处理太快了,CPU 速度快,外设慢,文件缓冲区起到了“数据中转站”的作用减少 I/O 频繁调用,提高系统吞吐量。统一写入可以提高效率。

重定向

进程打开文件,需要给文件分配新的fd,fd的分配规则是使用当前最小的并且没有被使用的fd!

以上fd决对是3,4,5,6了,这是0,1,2都没有被关闭,都在用的情况。

接着我们将1关闭,1是标准输出流吧,printf应该向标准输出流显示器写入对吧,为什么却写入到了文件中,因为标准输出流被重定向了

很显然,第一个自创制的文件的fd被换成1了,那printf是拿着1的去匹配的标准输入流的呀,自然就匹配到文件了。那这个标准输入流不就没有对应的fd了吗,成为没有指针指向的文件,这种没有指向的文件就会被操作系统关掉的,不用了。

这么关闭再重新创建比较不雅观,我们一般重定项会选择使用dup2函数进行完成。

dup2重定向

这个dup2是一个系统调用

重点看dup2,这个函数的意思是将相对于原本的fd拷贝成新的fd,就是用一个新的fd来替换原本的fd,可以看出这个最后一个参数新的fd是我们的目标,将其带入上面的代码关闭的就是,我们要一直使用第一个自我创建的fd来替换原本标准输出流的fd(1),所以目标就是1,相对于替换之后的oldfd就是原本的fd,dup2(fd,1)。

如下:

成功写入文件:原本是直接输出屏幕的。

所以这个替换的机制是什么样的:

原本3指向新打开的文件,现在使用dup2进行替换,就直接拷贝3的指针的地址然后覆盖在1的位置,然后改变指向,指向新打开的文件,这样原本指向标准输出流的指针就不存在了。标准输入流这个文件就没有指针可以指向它了,跟个孤儿一样,最后被操作系统关闭。


http://www.kler.cn/a/564454.html

相关文章:

  • React + TypeScript 实现数据模型驱动 SQL 脚本生成
  • 阿里开源正式开园文生视频、图生视频模型-通义万相 WanX2.1
  • 使用AGM迭代公式和高精度数学计算开源库gmp计算圆周率小数点后1000位
  • SpringBoot整合SpringSecurity、MyBatis-Plus综合实例:认证、授权
  • Cannot find a valid baseurl for repo: base/7/x86_64
  • 从零构建知识库:AI如何实现“问题即答案”?
  • 学习路程八 langchin核心组件 Models补充 I/O和 Redis Cache
  • 在android studio上使用rknn模块下面的yolov8_pose模型
  • 嘉孚朗SDP系列伺服螺丝刀使用介绍
  • C# 确保程序只有一个实例运行
  • shell脚本的相关练习--->分支结构---->循环结构
  • yolo11 training benchmark [i7-13700 vs nvidia 3090]
  • Staruml软件的介绍安装uml类图的绘制流程
  • 第8章:流式海啸:数据重构
  • 8、HTTP/1.0和HTTP/1.1的区别【高频】
  • information_schema.processlist 表详解
  • Stale file handle
  • TCP 缓冲区核心机制
  • 为什么要进行软件测试?
  • 前端或者后端通常用到数组使用方式