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

Linux系统编程-标准I/O与系统I/O的比较

目录

一. 标准I/O与系统I/O

1.1 标准I/O与系统I/O的区别

1、标准I/O

2、系统I/O

3、总结

二. 标准I/O

2.1 标准I/O的缓冲机制

2.1.1 标准I/O的缓冲模式:

缓冲区:

行缓冲模式:

全缓冲模式:

无缓冲模式:

2.1.2 fflush()函数

2.1.3 标准I/O合并系统调用

命令:strace

一. 标准I/O与系统I/O

1.1 标准I/O与系统I/O的区别

文件I/O标准I/O
面向文件描述符fd面向文件流指针FILE*
由linux内核提供,属于系统调用,跨平台可移植性差C标准库提供,跨平台可移植性好
无缓冲区,实时性高,可以用在对硬件的控制上有缓冲区,实现数据缓冲,避免频繁的在用户态和内核态之间切换,提高了效率
可以操作普通文件,也可以操作硬件相关的设备类文件,管道,套接字主要用在对普通文件(-)的读写上,文本文件用的多

1、标准I/O

标准I/O具有缓存机制,可以合并系统调用

2、系统I/O

系统I/O每调用一次都会完成从user态kernel态的切换,实时性高

3、总结

标准I/O与系统I/O的区别在与响应速度(实时性)与吞吐量:

标准I/O的吞吐量大,效率高

系统I/O的实时性强

二. 标准I/O

2.1 标准I/O的缓冲机制

首先,来看一段程序:

这里直观的感受是打印出第一个printf的内容,然后进入死循环,但结果不是这样的:

int main() { printf("before while(1)"); while(1); printf("after while(1)"); return 0; }

结果:直接进入了死循环,没有打印,这是因为终端是行缓模式

2.1.1 标准I/O的缓冲模式:

缓存区的作用:大多情况下是好事---合并系统调用

缓存模式解释设备
行缓冲模式

遇到\n刷新

程序退出时刷新

缓冲区满了刷新

强制刷新

缓冲区大小1024字节(1k)

主要用于人机交互的界面

标准输出(终端)

全缓冲模式

缓冲区满了刷新

文件关闭刷新

程序退出刷新

强制刷新

缓冲区大小4096字节(4k)

主要用于对文件的读写(普通文件)

文件操作

默认(除了终端)

无缓冲模式需要立即输出的内容strderr
缓冲区:

高速设备和低速设备进行交互时,为了匹配低速设备的速率,需要在高速设备和低速设备之间增加一个缓冲区,用于数据缓冲

行缓冲模式:

换行刷新:

int main() { printf("hello world\n");//换行刷新 while(1); return 0; }

结果:

强制刷新:

int main() { printf("hello world");//强制刷新 fflush(stdout); while(1); return 0; }

结果:

满了刷新:

int main() { while(1){ printf("hello world"); usleep(100000); } return 0; }

结果:可知行缓冲的大小是1024字节

程序退出刷新:

int main() { printf("hello world"); return 0; }

结果:

全缓冲模式:

满了刷新:

int main() { FILE *fp = fopen("1.txt", "w"); if(fp == NULL){ perror("fopen():"); return -1; } while(1){ fputs("hello world", fp); usleep(10000); } return 0; }

结果:从这里也可以看出,全缓冲的缓冲区大小是4096字节,是以4096的整数倍增加的

无缓冲模式:

stderr:

int main() { fprintf(stderr,"hello world"); return 0; }

结果:

这里介绍一个强制刷新缓冲区的函数:fflush()

2.1.2 fflush()函数

作用:强制刷新指定流的缓冲区

1、对于输出流而言,调用 fflush() 会强制将给定输出或更新流的用户空间缓冲区中的所

有数据进行写入操作,具体操作是通过该流的底层写入函数来实现的。

2、对于与可寻址文件(例如磁盘文件,但不包括管道或终端)相关的输入流,调用

fflush() 会清除从底层文件中读取但尚未被应用程序使用的任何缓冲数据

3、该流的开启状态未受任何影响。

4、如果流参数为 NULL,则 fflush() 函数会刷新所有打开的输出流。

返回值:成功返回0失败返回-1并且设置error

由于终端是行缓存模式,则上面那段程序可以做以下修改使其打印出内容:

int main() { printf("before while(1)\n"); while(1); printf("after while(1)\n"); return 0; }

结果:

也可以使用fflush来强制刷新缓冲区:

int main() { printf("before while(1)"); fflush(stdout); while(1); printf("after while(1)"); fflush(NULL); return 0; }

结果:

2.1.3 标准I/O合并系统调用

这里可以通过一个程序来说明标准I/O缓冲区合并系统调用的作用:

代码:可能打印出ababab

int main() { putchar('a'); write(1, "b", 1); putchar('a'); write(1, "b", 1); putchar('a'); write(1, "b", 1); return 0; }

结果:

命令:strace

这里介绍一个命令:strace + 可执行文件:用来看一个可执行文件的系统调用是如何发生的。使用此命令来查看这段程序使用的系统调用:

可以看到三次putchar被合并为了一次write系统调用,这种合并系统调用大幅降低内核态 / 用户态切换耗时

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

相关文章:

  • OOTDiffusion推理加速实战:从分钟级到秒级的硬核调优之路
  • (干货整理)亲测好用的AI论文写作软件,毕业党收藏备用
  • 基于MOSFET与RC电路的延时开关设计:从原理到实践
  • FLUX.1-dev精度评估:ClipScore与Hpsv2测试全流程
  • 终极免费开源甘特图工具:GanttProject如何解决你的项目管理难题?
  • Linux 内核中的 sendfile:从上下文切换到零拷贝
  • 终极指南:5分钟快速上手RPG Maker解密工具,轻松提取加密游戏资源
  • 网络通信详细总结
  • AI剪辑长视频做录播,重点从来不是画面!
  • 终极指南:3分钟快速上手RPG Maker解密工具,轻松提取加密游戏资源
  • 如何让旧Mac焕发新生:3步解锁突破性系统兼容方案
  • Python自动化实战:从脚本工具到自动化框架的演进之路
  • Android通用SDR驱动:将移动设备变成专业无线电接收站的技术革命
  • 当AI学会了“理解“工厂:制造业企业本体语义模型实战
  • 国家中小学智慧教育平台电子课本下载三步法:轻松获取PDF教材的完整方案
  • 抖音下载器技术深度解析:多策略智能降级架构与高效内容管理方案
  • 如何让2008-2017年的老款Mac焕发新生:OpenCore Legacy Patcher完全指南
  • 如何轻松解决Cursor试用限制?免费重置工具使用完全指南
  • 从‘灰光’到‘彩光’:手把手图解光模块在OTN网络中的角色转换与配置要点
  • 「阅读」APP书源导入完全指南:告别书荒,轻松获取全网小说资源
  • 工业防爆监控技术简析:湖北高危场景选型技术规范与落地方案参考
  • 花岗岩铣削刀具加工效能的系统方案【附数据】
  • 无人机飞行数据分析终极指南:UAV Log Viewer完整教程
  • Limbus Company自动化助手:告别重复操作,重新发现游戏乐趣
  • 齿轮传动系统若干动力学问题解析【附仿真】
  • 工业防爆监控选型科普|湖北区域 5 家优质供应商技术特点汇总
  • 【RT-DETR实战】122、算能(Sophgo)TPU平台部署探索:从模型转换到性能调优的血泪史
  • analysis-ik性能优化:亿级中文文本分词的最佳实践与调优策略
  • 从国内标杆到海外主力!苏州大向集成房屋中标乌克兰战后安置房项目,印证硬核制造实力 - 新闻快传
  • 3分钟上手!终极AI图像质量评估工具让海量图片自动筛选不再是难题