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

文件-语言-系统:基础IO-2.0——IO重定向接口,语言层缓冲区,系统级缓冲区。内核级分析!

@bit::Shadow
✧(≖ ◡ ≖✿

目录

重定向接口dup2()

">" ">>" "<"

函数原型

输出重定向1和2的使用

文件描述符表

./a.out运行:

"./a.out >"默认重定向是fd == 1

合并标准输入输出

缓冲区

什么是缓冲区?

缓冲区的意义?

语言与系统中的缓冲区

语言级

文件操作

fd未提前关闭:

fd提前关闭:

系统调用接口较于库函数的强关联性

为什么stdout下write在最后打印到文件内却是第一个打印呢?

父子进程分别退出导致语言层缓冲区双倍刷新

原因:

为什么设计“语言层”与“系统层”缓冲区分离的机制?


衔接上篇文件IO-1.0

重定向接口dup2()

">" ">>" "<"

">"输出重定向,清空并新写入。
">>"追加重定向,追加内容到指定文件/流。
"<"输入重定向,例:cat < log.txt 就是 cat log.txt 。

标准输出1与标准错误2指向的均是标准错误,不过fd不同。

函数原型

int dup2(int oldfd, int newfd);

功能:基于操作系统“只认文件标识符fd”来定位输出对象的前提,让newfd指向oldfd指向的文件/设备成功则返回新fd否则返回-1。

当我们进行以fd标识的输入输出读取等操作时,就会因为"fd"的重定向导致操作对象改变!

例:

dup2(fd, 1); //将标准输出流内的数据写入到fd指向的文件内。

int main() { int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); //fd == 3 dup2(fd, 1); printf("预备标准输出流内容\n"); const char* s = "nihao\n"; write(fd, s, strlen(s)); close(fd); return 0; }

运行发现显示器并未出现:“预备标准输出流内容”的输出而是文件log.txt内被写入。

由此也可以体现:Linux作为独立于Win操作系统的存在,正是其操作系统默认打开的0:标准输入流,1:标准输出流及2:标准错误流。文字/符号/图形才得以显示。

输出重定向1和2的使用

文件描述符表

OS只识别文件fd:

☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆

1:标准输出流
2:标准错误流

两者均是像显示器打印。

运行以下代码:

#include <cstdio> #include <iostream> int main() { //向标准输出进行打印,stdout,cin->1 std::cout << "hello cout" << std::endl; printf("hello printf\n"); //向标准错误进行打印,stderr,cerr->2, std::cerr << "hello cerr" << std::endl; fprintf(stderr, "hello stderr\n"); return 0; }

./a.out运行:

"./a.out >"默认重定向是fd == 1

err内容输出到屏幕:

./a.out 2 :

合并标准输入输出

./a.out > log.txt 2 >&1

错误方式:./a.out > log.txt 2 >> 1

缓冲区

什么是缓冲区?

简单理解:缓冲区是一块内存区域

缓冲区的意义?

尽量集中数据、同时处理,提高交互效率。

语言与系统中的缓冲区

语言层系统层分别有自己的缓冲区,两者缓冲区的关系是各自独立间接相关

语言级

缓冲区刷新条件:

1.强制刷新。如:fflush()函数
2.满足特定条件自动刷新。例:缓冲区满、行刷新/行缓冲“\n”。
3.进程退出。如:程序结束、exit(-1)强制退出。

文件操作

语言对文件的操作本质是系统对磁盘的IO管理,因此涉及到语言层缓冲区与系统层缓冲区的交互。

(非全缓冲是行缓冲(一般缓冲))语言缓冲区到系统缓冲区传递条件:fd(文件标识符)+ 系统调用(像:write())

printf/fprintf/fwrite/fputs均是库函数,本质内部均封装write”。

也就是说若fd使用close提前关闭就会输出混乱。

fd未提前关闭:

fd提前关闭:

语言采用行刷新后关闭

不会输出在fd:

原因及解决方案:

\n触发行缓冲刷新是C 标准 I/O 行为而不是文件描述符的概念,前提是stdout被终端关联且缓冲模式是行缓冲。如果你发现log.txt没有内容,说明stdout在程序启动时就不是行缓冲(例如被重定向或从非终端启动),应使用fflush(stdout)强制刷新。

系统调用接口较于库函数的强关联性

write为例:

将buf内容写到fd指向的文件内

#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);

显示器与文件操作下的对比:

代码:

void test4() { //三种库函数写入到显示器 printf("printf\n"); fprintf(stdout, "fprintf\n"); const char* s = "fwrite\n"; fwrite(s, strlen(s), 1, stdout); //系统调用 const char* ss = "write\n"; write(1, ss, strlen(ss)); }

显示器:

文件:

为什么stdout下write在最后打印到文件内却是第一个打印呢?

原因:因为语言层IO想要进入文件必须经“语言---系统层面”的区域转换,作用时“write系统调用”下距离OS缓冲区更近,因此优于库函数写入到文件内。而呈现出虽然代码从上向下执行但系统调用优先特殊逻辑关系链。

父子进程分别退出导致语言层缓冲区双倍刷新

int main() { //库函数 printf ("hello printf\n"); fprintf (stdout, "hello fprintf\n"); const char *s = "hello fwrite\n"; fwrite (s, strlen (s), 1, stdout); //系统调用 const char *ss = "hello write\n"; write (1, ss, strlen (ss)); //??? fork(); }

运行:

原因:

PCB下双层退出导致二次刷新,从而形成了文件IO双倍的现象:


为什么设计“语言层”与“系统层”缓冲区分离的机制?

系统调用是操作系统亲临执行任务,操作系统是最忙的存在。简而言之:系统调用成本太高!的像malloc时顺序表时两倍的扩容机制、vector、tcmalloc等设计均是为优化这一影响而设计出的解决方案。

感谢观看
求关注

http://www.jsqmd.com/news/886735/

相关文章:

  • virtualbox 宿主(win)与虚拟机(linux)共享文件夹
  • METSO A413248自动化系统
  • AI 充电枪智能功率 MOSFET 完整选型方案
  • AIGC工作流平台实战复盘:从需求到上线的完整项目经验与避坑指南
  • 为什么你的DeepSeek微调代码正在悄悄越权?——基于AST+CFG融合分析的5分钟自检清单
  • MySQL 死锁产生原因与避免
  • 安全测试入门:每个开发都应该知道的10个常见漏洞
  • SMUDebugTool终极指南:如何深度掌控AMD Ryzen处理器的隐藏性能
  • 中兴光猫终极管理指南:解锁工厂模式与Telnet权限的实战教程
  • 如何进行TVA仿真引擎的“光照地狱”训练?
  • rk35xx 通过recovery升级问题
  • ssm高校推免报名系统(10102)
  • 企业级AI语音合成采购决策白皮书(2024真实报价单首次公开)
  • 本地Windows容器迁移至云服务器
  • 【MySQL数据库 | 第一篇】 概述
  • # AI音乐生成API的可控性与专业化演进研究
  • 配置OpenClaw Agent使用Taotoken作为后端模型提供商
  • 【Qwen3.6】关键技术:线性注意力(Linear Attention/DeltaNet)和标准多头注意力(Standard Attention)混合
  • 2024年网盘下载终极免费解决方案:八大平台直链解析技术深度解析
  • Windows终极PDF处理工具:3步免费安装Poppler完整指南
  • 如何处理AI生成代码中的错误
  • 5分钟搭建原神私服:KCN-GenshinServer终极图形化解决方案
  • DeepSeek幻觉问题深度复盘(2023–2024真实故障库首发):从token级偏差到语义坍塌的全链路溯源
  • Owl-Alpha 新手快速上手指南
  • LSTM 算法的完整计算过程
  • MySQL GROUP BY 原理与优化
  • 基于双T振荡器的正弦波LED调光电路设计与实践
  • Linux系统Vim编辑器
  • 你的企业还在用“人海战术”处理发票和报表?2026智能体进化论
  • 别再死磕理论了!用Python手搓一个蒙特卡洛强化学习小游戏(附完整代码)