【玩转Linux】标准io缓冲区的操作

  • (꒪ꇴ꒪ ),hello我是祐言
  • 博客主页:C语言基础,Linux基础,软件配置领域博主🌍
  • 快上🚘,一起学习!
  • 送给读者的一句鸡汤🤔:
  • 集中起来的意志可以击穿顽石!
  • 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏

一、缓冲区概念

        标准I/O缓冲区是用于提高I/O性能的一种机制,它位于标准C库中,并由标准I/O函数自动管理。标准I/O库通过在内存中创建缓冲区来减少频繁的系统调用,从而提高读写操作的效率。

标准I/O库使用三种类型的缓冲区:

        1. 全缓冲(Fully Buffered)

         当使用全缓冲模式时,标准I/O库会在内存中创建一个较大的缓冲区(通常大小为BUFSIZ),直到缓冲区被填满或遇到换行符('\n')时才会将数据写入磁盘。全缓冲适用于文件和大量数据的I/O操作,减少了系统调用的次数,提高了效率。

        2. 行缓冲(Line Buffered

         行缓冲模式下,标准I/O库会在遇到换行符('\n')时将数据写入磁盘,或者当缓冲区被填满时也会进行写入。行缓冲适用于终端设备(如终端窗口),可以保证每行数据都及时输出,方便用户查看输出结果。

        3. 无缓冲(Unbuffered)

         无缓冲模式下,标准I/O库会立即将数据写入磁盘,不使用缓冲区。每次调用I/O函数都会导致实际的系统调用,适用于需要立即刷新数据到磁盘的场景,如实时输出错误信息。

        标准I/O函数会自动选择合适的缓冲模式,但你也可以使用setvbuf函数来显式地设置缓冲模式和自定义缓冲区。

        对于标准输入(stdin)、标准输出(stdout)和标准错误(stderr),它们的默认缓冲模式通常是行缓冲(对于交互式终端)或全缓冲(对于文件和重定向)。

        需要注意的是,标准I/O缓冲区是由C库管理的,所以在使用标准I/O函数时,要确保及时刷新缓冲区,以免数据在缓冲区中滞留而未及时输出。可以使用fflush函数来手动刷新缓冲区,确保数据及时写入磁盘或终端。

二、SETBUF函数

  setbuf函数用于设置标准I/O流的缓冲区,从而控制I/O的缓冲方式。它允许你自定义缓冲区,或者禁用缓冲。setbuf函数的原型如下:

#include <stdio.h>
​
void setbuf(FILE *stream, char *buffer);

        参数说明:

  • stream:指向要设置缓冲区的文件流,可以是标准输入(stdin)、标准输出(stdout)、标准错误(stderr)或者其他已打开的文件流。

  • buffer:指向自定义缓冲区的指针。如果传递NULL,则表示禁用缓冲,使I/O变为无缓冲。

setbuf函数允许两种方式的缓冲:

  1. 全缓冲:如果buffer指向一个大小大于0的缓冲区,那么I/O操作将使用全缓冲模式。这意味着在填满整个缓冲区或者遇到换行符('\n')时,才会进行实际的I/O操作。

  2. 无缓冲:如果buffer为NULL,或者大小为0,那么I/O操作将变为无缓冲模式。这意味着每次调用输出函数(printfputchar等)或者输入函数(scanfgetchar等),都会立即进行I/O操作,而不会在内存中缓冲数据。

在使用setbuf函数时,要注意以下几点:

  1. 调用setbuf函数应该在打开文件流或者任何I/O操作之前,否则可能不会生效。

  2. 如果要使用自定义的缓冲区,确保缓冲区足够大,以避免缓冲区溢出。

  3. 如果设置为无缓冲,要注意频繁的I/O操作可能会导致性能下降,因为每次调用I/O函数都会进行实际的I/O操作,这会增加系统开销。

  4. 当使用自定义缓冲区时,不要在buffer指向的缓冲区被释放或者失效后再进行I/O操作,以免导致未定义的行为。

        示例:使用全缓冲模式设置标准输出(stdout)的缓冲区为一个大小为BUFSIZ(通常是1024字节)的缓冲区。

#include <stdio.h>
​
int main() {char buf[BUFSIZ];setbuf(stdout, buf);
​printf("This will be buffered\n");fflush(stdout); // 强制刷新缓冲区,立即输出printf("This will also be buffered\n");
​return 0;
}

        示例:禁用标准输出(stdout)的缓冲区,使其变为无缓冲模式。

#include <stdio.h>
​
int main() {setbuf(stdout, NULL); // 禁用缓冲
​printf("This will be immediately output\n");printf("No buffering in this case\n");
​return 0;
}

三、SETVBUF函数

   setvbuf函数也是用于设置标准I/O流的缓冲方式,与setbuf函数类似,但提供更灵活的缓冲控制。setvbuf函数允许你自定义缓冲区,并且可以指定缓冲类型,包括全缓冲、行缓冲和无缓冲。它的原型如下:

#include <stdio.h>
​
int setvbuf(FILE *stream, char *buffer, int mode, size_t size);

参数说明:

  • stream:指向要设置缓冲区的文件流,可以是标准输入(stdin)、标准输出(stdout)、标准错误(stderr)或者其他已打开的文件流。

  • buffer:指向自定义缓冲区的指针。如果传递NULL,则会使用系统默认的缓冲区。

  • mode:指定缓冲类型,可以是以下值之一:

    • _IOFBF:全缓冲模式。使用指定的缓冲区,并在填满整个缓冲区时才进行实际的I/O操作。

    • _IOLBF:行缓冲模式。使用指定的缓冲区,并在遇到换行符('\n')时才进行实际的I/O操作。

    • _IONBF:无缓冲模式。禁用缓冲,每次调用I/O函数都会立即进行实际的I/O操作。

  • size:指定缓冲区大小。对于全缓冲和行缓冲模式,size表示缓冲区大小;对于无缓冲模式,size被忽略,可以设置为0。

   setvbuf函数的返回值是非零值表示成功,返回0表示失败。

        另外在使用setvbuf函数时,可以根据需要设置不同类型的缓冲模式和缓冲区大小。对于全缓冲和行缓冲,需要确保缓冲区足够大,以避免缓冲区溢出。而对于无缓冲模式,要注意频繁的I/O操作可能会导致性能下降。

        示例:使用全缓冲模式设置标准输出(stdout)的缓冲区为一个大小为BUFSIZ(通常是1024字节)的缓冲区。

#include <stdio.h>
​
int main() {char buf[BUFSIZ];setvbuf(stdout, buf, _IOFBF, BUFSIZ);
​printf("This will be buffered\n");fflush(stdout); // 强制刷新缓冲区,立即输出printf("This will also be buffered\n");
​return 0;
}

        示例:使用行缓冲模式设置标准输出(stdout)的缓冲区。

#include <stdio.h>
​
int main() {char buf[BUFSIZ];setvbuf(stdout, buf, _IOLBF, BUFSIZ);
​printf("This will be line buffered\n");printf("This will also be line buffered\n");
​return 0;
}

        示例:禁用标准输出(stdout)的缓冲区,使其变为无缓冲模式。

#include <stdio.h>
​
int main() {setvbuf(stdout, NULL, _IONBF, 0); // 禁用缓冲
​printf("This will be immediately output\n");printf("No buffering in this case\n");
​return 0;
}

        但要注意:在某些系统上,对标准输入(stdin)和标准输出(stdout)的缓冲设置可能不会生效,因为它们是由标准库提供的,并且可能使用了系统默认的缓冲设置。所以在实际使用中,最好将setvbuf函数用于文件流而不是标准输入和标准输出。

        更多C语言Linux系统相关文章,关注专栏:

   手撕C语言

            玩转linux

📢写在最后

  • 今天的分享就到这啦~
  • 觉得博主写的还不错的烦劳 一键三连喔~
  • 🎉感谢关注🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/8840.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Golang] Viper原理以及详细使用案例

文章目录 什么是 Viper&#xff1f;基础配置引入依赖&#xff1a;动态监听原理分析&#xff1a;监听原理分析 Config.yaml文件配置Viper文件配置 什么是 Viper&#xff1f; 介绍&#xff1a;用于处理配置文件中解析和读取配置文件 优点&#xff1a;支持多种配置格式&#xff0…

新老联手,火花四溅?大众汽车与小鹏汽车达成长期合作框架协议

7 月 26 日资讯&#xff0c;大众汽车宣布与小鹏汽车达成长期合作框架协议&#xff0c;并在官网中正式宣布&#xff0c;大众是老牌油车领军代表&#xff0c;小鹏则是新势力中的佼佼者&#xff0c;新老强强联手&#xff0c;又会碰撞出怎样的火花呢&#xff1f; 现阶段大众计划与…

Postman学习之常用断言

什么是断言&#xff1f; 断言——就是结果中的特定属性或值与预期做对比&#xff0c;如果一致&#xff0c;则用例通过&#xff0c;如果不一致&#xff0c;断言失败&#xff0c;用例失败。断言&#xff0c;是一个完整测试用例所不可或缺的一部分&#xff0c;没有断言的测试用例…

leetcode每日一练-第98题- 验证二叉搜索树

一、思路 因为要验证多个节点是否是二叉搜索树,因此使用递归 二、解题方法 设计一个递归函数 helper(root, lower, upper) 来递归判断&#xff0c;函数表示考虑以 root 为根的子树&#xff0c;判断子树中所有节点的值是否都在 (l,r)的范围内&#xff08;注意是开区间&#x…

git配置

git查看配置&#xff1a;git config --global --list git配置&#xff1a; git config --global user.name "yumlu" git config --global user.email "yumlucisco.com" git config --global core.editorvim git权限&#xff0c;添加密钥&#xff1a; …

工厂方法模式——多态工厂的实现

1、简介 1.1、概述 在工厂方法模式中&#xff0c;不再提供一个统一的工厂类来创建所有的产品对象&#xff0c;而是针对不同的产品提供不同的工厂&#xff0c;系统提供一个与产品等级结构对应的工厂等级结构。 1.2、定义 工厂方法模式&#xff08;Factory Method Pattern&am…

Filebeat学习笔记

Filebeat基本概念 简介 Filebeat是一种轻量级日志采集器&#xff0c;内置有多种模块&#xff08;auditd、Apache、Nginx、System、MySQL等&#xff09;&#xff0c;针对常见格式的日志大大简化收集、解析和可视化过程&#xff0c;只需一条命令即可。之所以能实现这一点&#…

设计模式原则

1、设计模式七大原则 1.1 设计模式的目的 编写软件过程中&#xff0c;程序员面临着来自 耦合性&#xff0c;内聚性以及可维护性&#xff0c;可扩展性&#xff0c;重用性&#xff0c;灵活性 等多方面的挑战&#xff0c;设计模式是为了让程序(软件)&#xff0c;具有更好 代码重…

Mkdocs中利用Js实现大小圈鼠标拖动样式

在docs/javascripts/extra.js下复制粘贴&#xff1a; var CURSOR;Math.lerp (a, b, n) > (1 - n) * a n * b;const getStyle (el, attr) > {try {return window.getComputedStyle? window.getComputedStyle(el)[attr]: el.currentStyle[attr];} catch (e) {}return …

k8s核心概念

一、集群架构与组件 1&#xff0c;相关组件 【1】 master node三个组件 k8s的控制节点&#xff0c;对集群进行调度管理&#xff0c;接受集群外用户去集群操作请求master node 组成&#xff08;四个组件&#xff09;&#xff1a;控制面 API Server&#xff1a;通信kube-Sche…

大模型的淘金时代,HPE给出了一份智能经济“奇点”攻略

进入2023年&#xff0c;ChatGPT引发了一个新的AI时代——大模型时代。陆奇说&#xff1a;“我已经跟不上大模型时代的狂飙速度了&#xff01;”大模型引发了AI产业整体升级换代&#xff0c;各种大模型层出不穷&#xff0c;科技公司纷纷入局&#xff0c;AI创业公司再次雨后春笋般…

【LeetCode】79.单词搜索

题目 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或…

LabVIEW开发环境试验箱控制器

LabVIEW开发环境试验箱控制器 环境或气候试验箱是一种外壳&#xff0c;用于模拟各种材料&#xff08;包括工业产品、生物物质、复合材料、电子设备和航空航天部件&#xff09;的特定环境条件&#xff0c;并评估调节对这些材料的影响。 环境试验箱&#xff08;ETC&#xff09;…

08.计算机网络——其他重要协议和技术

文章目录 DNSICMPNAT代理服务器 DNS DNS是一整套从域名映射到IP的系统 ​ TCP/IP中使用IP地址和端口号来确定网络上的一台主机的一个程序&#xff0c;但是IP地址不方便记忆&#xff0c;于是人们发明域名&#xff0c;其本质是一个字符串&#xff0c;映射了它和IP地址的关系。 …

【iOS】—— RunLoop和多线程相关问题总结

RunLoop 1. 讲讲RunLoop&#xff0c;项目中有用到过吗&#xff1f; RunLoop 的基本作用&#xff1a;保持程序的持续运行&#xff0c;节省 CPU 的资源&#xff0c;提高程序的性能 &#xff08; 没有事情&#xff0c;就请休眠&#xff0c;不要功耗。有事情&#xff0c;就处理&a…

【JavaSE】运算符

【本节目标】 1. 熟练掌握各种运算符 这部分内容和C语言的位运算相似&#xff0c;可以参考这篇文章&#xff1a;【C语言】操作符详解 目录 1. 什么是运算符 2. 算术运算符 3. 关系运算符 4. 逻辑运算符 5. 位运算符 6. 移位运算(了解) 7. 条件运算符 1. 什么是运算符 …

day31贪心算法 用最少数量的箭引爆气球 和无重叠区间

题目描述 题目分析&#xff1a; x轴向上射箭&#xff0c;12一支&#xff0c;重叠的需要一支&#xff0c;3-8一支&#xff0c;7-16一支 返回2&#xff1b; 就是让重叠的气球尽量在一起&#xff0c;局部最优&#xff1b;用一支弓箭&#xff0c;全局最优就是最少弓箭&#xff1b…

SQL ORDER BY 关键字

ORDER BY 关键字用于对结果集进行排序。 ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序。 ORDER BY 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序&#xff0c;您可以使用 DESC 关键字。 ORDER BY 子句后面的列名指示按哪些列进行排序。如…

如何才能做Cox呢?今天带来Cox回归分析步骤详解

Cox回归是生存分析中运用最多的一个模型&#xff0c;又称为比例风险回归模型(proportional hazards model)。是由英国统计学家D.R.Cox在1962年提出的&#xff0c;为了表示对他的尊敬&#xff0c;所以大家以他的名字命名这个模型。这是一种半参数回归模型&#xff0c;以结局和生…

数据结构【绪论】

数据结构入门级 第一章绪论 什么是数据结构&#xff1f;什么是数据类型&#xff1f; 程序数据结构算法 一、基本概念&#xff1a; 数据&#xff1a;指所有能被计算机处理的&#xff0c;无论图、文字、符号等。数据元素&#xff1a;数据的基本单位&#xff0c;通常作为整体考…