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

【文件fd】深入理解重定向和缓冲区

目录

1.重定向

1.1dup2 

2.缓冲区

2.1什么是缓冲区

2.2为什么存在缓冲区

2.3缓冲区的刷新策略

2.4查看源码​

3.0/1/2

3.1 0/1/2是什么&为什么存在

3.2 2和1区别

3.3 2为什么存在


1.重定向

  • 重定向的本质:是在内核中改变文件描述符表特定下标的内容和上层无关❗、
  • 上层不变,OS只给上层一个数字。下标也不变,主要是变文件描述符表(指针数组)元素内容。
  • 重定向是OS系统级别的修改,struct files_struct是内核数据结构。要修改文件描述符表中元素(指针/指向)必须要OS给用户提供系统调用。

1.1dup2 

  • man 2 dup2
  • int dup2(int oldfd, int newfd);
  • dup2可以在底层帮助完成两个文件描述符表(指针数组)的元素值拷贝。
  • 做两个整数的拷贝(fd)本质:文件描述符表(指针数组)下标fd对应的数组元素(指针)内容的拷贝。
  • dup2()  makes newfd be the copy of oldfd
  • 记忆:最后只会保留oldfd,也就是要重定向的内容
  • >和>>二者区别是:打开的方式选项不同清空&追加  O_TRUNC&O_APPEND
  • 重定向后 没有文件描述符指向的文件会被自动关闭。一个文件有两个文件描述符指向。
  • struct file内部会存在int ref_count(引用技术)
  • 文件有几个指向ref_count就是几个。为0的文件会自动关闭。
  • int ref_count(引用技术):就是有多少个指针指向文件对象。

  

【输出重定向>】

【追加重定向>>】

 

  •  shell进程在启动的时候,就会在/dev/pts创建设备文件。(默认打开的显示器/键盘等)
  • 若我们新打开一个窗口(终端),这个终端也是进程打开的设备文件,也会在/dev/pts目录下创建自己对应设备文件。(字符设备)Linux底下一切皆文件。
  • C语言编程使用printf时,默认会在当前进程所处的终端打印数据。(3号终端)
  • 新打开的终端是2号。将数据从3号终端重定向2号终端。

 

2.缓冲区

2.1什么是缓冲区

 所谓缓存区就是把数据临时放在一段内存空间里。

2.2为什么存在缓冲区

  •  计算机中存在很多缓冲区,既有用户级的缓冲区,又有内核级的缓冲区。每一种缓冲区都有自己特殊的作用。注❗缓冲区存在两种益处
  • 每一个文件都有一份自己的缓冲区❗

解耦:

  • 内核缓存刷新到外设:用户把数据交给OS的内核缓冲区,刷新到外设都不用管了。(语言和硬件解耦了)
  • 用户级缓存刷新到内核缓存:printf只需要把数据交给用户缓存区,不用管C语言怎么把数据刷新到内核的。(用户和系统解耦了)

提高效率(❗重点谈)提高效率是提高使用者的效率 

用户printf☞用户级缓存☞内核级缓存☞外设

  • 调用系统调用是有成本的(系统调用是需要OS配合,OS很忙的)所以少调用,效率就高。
  • 编程语言是需要注重用户体验的,只有把用户体验服务搞好了,才会有更多的人去使用这门语言。
  • 编程语言提供的接口,只需要把数据交给缓冲区,立刻旧可以返回。缓冲区的存在是提高使用者的效率。有缓冲区的存在,是提高printf/fprintf等接口的使用效率。
  • 编程语言的接口使用就会比较快(因为只是写道缓存中,没有到内核),用户体验好。
  • 使用语言提供的接口,在用户级缓存积累多次。等待OS配合一次性就刷新大量数据到内核,提高OS整体的效率。
  • 内核级缓存存在提供使用系统调用的人的体验(因为外设硬件很慢)
  • 语言为用户考虑,系统为语言考虑。
  • 综上:提高使用者的效率。提高刷新IO的效率。给上层提供高效的IO体验,间接提高整体的效率。

2.3缓冲区的刷新策略

  • 立即刷新: 相当于没有缓存,还多了一次拷贝(常见),数据立即从内核同步到外设。

  1. 语言:fflush

  2. 系统:man 2 fsync

  • 行刷新:显示器是行刷新。照顾用户的查看习惯。

  • 全缓冲:缓冲区满了才刷新。普通文件。

特殊情况:

  • 进程在退出时,无论是用户/内核级的缓存,系统和语言都会自动刷新。

  • 强制刷新(ffush/fsync)

  • 注❗:缓冲区的刷新策略和是 用户级缓冲区。内核级不关心。

  • 不同的平台对刷新的策略是不一样的

【进程退出:exit和_exit】

【进度条:\n和fflus】 

【看代码☞说明现象】

2.4查看源码

 

3.0/1/2

3.1 0/1/2是什么&为什么存在

  • 0:标准输入,键盘。
  • 1:标准输出,显示器。
  • 2:标准错误,显示器。
  • 程序需要和人交互的,所以必须要从特定的设备获取数据,对数据处理之后,输出结果。方便用户动态的获取数据和查看数据。

3.2 2和1区别

  • fd为1/2的都指向同一个显示器文件(往同一个终端打印)。
  • 当把数据往显示器上打印:一切正常。
  • 当把数据重定向到普通文件中:
  • 1号下标对应内容改变了,2号下标对应内容没有改变。
  • > 标准输出重定向,只会改变1号下标的对应的内容。标准输出会重定向,标准错误不会重定向。

【往显示器上打印】 

【输出重定向>】 

3.3 2为什么存在

  • 当编程的时候。会产生两类消息,正确的消息和错误的消息。为了区分这两类消息。
  • 正确的消息往1里面打印。错误的消息往2里面打印即可。
  • 只需要做一次重定向就可以把正确和错误的信息在文件层面上分开即可。

【就想把1和2要打印内容一起重定向一个文件中】

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • python-局部求和(赛氪OJ)
  • 2024年有什么赚钱的副业推荐半年还清贷款,成功变现12.3w的全套玩法都放这里了!!!
  • linux用户组练习
  • FastAPI之Depends
  • Scrapy 爬取旅游景点相关数据(五)
  • 【LLM】-14-搭建问答系统
  • 天气曲线echarts
  • PHP常用函数
  • Opencv学习-LUT函数
  • 人工智能未来展望
  • 基于域名的虚拟主机、多虚拟主机的配置、基于ip的虚拟主机及上线静态的前端系统(商城系统)
  • jenkins服务器重启,构建记录消失
  • 结构型设计模式:适配器/代理
  • Qt——QTCreater ui界面如何统一设置字体
  • 设计用户登录与注册界面切换的HTML+CSS+JS代码
  • #Java异常处理
  • @angular/forms 源码解析之双向绑定
  • __proto__ 和 prototype的关系
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • Django 博客开发教程 8 - 博客文章详情页
  • Effective Java 笔记(一)
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • Java编程基础24——递归练习
  • js继承的实现方法
  • Laravel 实践之路: 数据库迁移与数据填充
  • Selenium实战教程系列(二)---元素定位
  • Spring-boot 启动时碰到的错误
  • text-decoration与color属性
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • yii2权限控制rbac之rule详细讲解
  • 测试如何在敏捷团队中工作?
  • 初识MongoDB分片
  • 经典排序算法及其 Java 实现
  • 前端性能优化--懒加载和预加载
  • 深度解析利用ES6进行Promise封装总结
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 我这样减少了26.5M Java内存!
  • 小程序01:wepy框架整合iview webapp UI
  • 移动端解决方案学习记录
  • 字符串匹配基础上
  • ​configparser --- 配置文件解析器​
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • # Redis 入门到精通(一)数据类型(4)
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • $L^p$ 调和函数恒为零
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (3)STL算法之搜索
  • (done) 两个矩阵 “相似” 是什么意思?
  • (function(){})()的分步解析
  • (二)JAVA使用POI操作excel
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (三)Kafka离线安装 - ZooKeeper开机自启