IO编程 之 缓冲篇

article/2025/9/22 7:02:28

涉及linux中IO编程的时候,我们总是不可避免地要跟各种各样的缓冲机制打交道,学好linux IO编程不是简单地掌握几个函数的用法就万事大吉,正确地运用IO需要对其缓冲机制全面的理解,切不可依葫芦画瓢,蒙混过关。


切入正题之前,我们先看一个简单的程序:


#include <stdio.h>
#include <errno.h>

#include <unistd.h> 


#define BUFSIZE 5*1024

int
main(void){
    FILE *fp1, *fp2;
    char buf[BUFSIZE];

    fp1 = fopen("src", "r");
    fp2 = fopen("des", "w");

    fgets(buf, BUFSIZE, fp1);
    fputs(buf, fp2);

    sleep(30);
    return 0;
}


其中src是一个只有一行的文本文件,这一行有4500个字符(即占用4.5k存储空间)。


注意到程序倒数第二行睡眠本分钟,我们在此期间查看两个相关文件,如下:

sleep结束之前src和des的大小

 

 

 

 

figure1. sleep函数结束之前两个文件src和des的大小 


程序运行结束后,我们再次查看两个相关文件,如下:

sleep结束之后src和des的大小

figure2. sleep函数结束之后两个文件src和des的大小


从这个图1可以清晰地看到,fputs函数在既没有遇到换行符,也没有被强制冲洗的情况下输出了4k大小的字符,原因在于标准IO库函数自动分配的缓存区满了,自动进行了缓存区冲洗,从而导致了真正的IO操作。记住,这4k数据是由于缓冲区满了之后通过fputs函数被刷新 出去的,而剩下的字符则跟fputs没有任何关系了,它们是由于程序最后调用了return 语句,退出进程的时候系统自动刷新所有的IO流以及关闭所有打开的文件句柄的时候被刷新至内核的。

 

举着个例子的原因在于,很多人不明白UNIX中所谓的行缓冲、全缓冲以及无缓冲本质是什么,总是很容易跟在程序中调用的fgets函数、fread函数的读取方式相混淆,甚至跟自定义的缓冲区(如上面例子中提到的buf)相混淆。

 

我们要搞清楚上面例子中的那些关系,必须着重强调的一点是:用户空间中实际开辟了两个缓冲区,一个是看得见那个buf,就是我们自己手工创建的,另一个是库函数中为我们创建的4k缓冲区。

 

这个缓冲区是怎么来的呢?注意到这句定义文件指针的语句没有:FILE *fp;其中FILE就是一个结构体,我们打开一个文件之后就利用句柄fp与实际内存中与此文件对应的那个结构体关联起来,这个结构体大致如下(在库函数源代码文件中的libio/libio.h中定义):

 


 

struct _IO_FILE {
  int _flags;        /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;    /* Current read pointer */
  char* _IO_read_end;    /* End of get area. */
  char* _IO_read_base;    /* Start of putback+get area. */
  char* _IO_write_base;    /* Start of put area. */
  char* _IO_write_ptr;    /* Current put pointer. */
  char* _IO_write_end;    /* End of put area. */
  char* _IO_buf_base;    /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */ 
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */
  ... ... ...

  ... ... ...

};


我们只关心红色标识的那两行,就是这两个字符指针,指向了一个4k大小的内存缓冲区,库函数把这个缓冲区作为与内核交互数据的场所,所谓的行缓冲、全缓冲、无缓冲都是相对这块内存区域而言的,绝非我们自己定义的那个buf,也跟fgets的按行读取模式没有什么关系。
它们的关系可以简单地用一下这幅图来表示:

 

实际上像fgets函数这样按行读取的函数,它的按行读取指的是把数据填充到自定义的那个buf时一行一行地读,最终是通过标准IO库里面的缓冲区跟具体文件交互的。


http://chatgpt.dhexx.cn/article/DlkLgT0j.shtml

相关文章

【蓝桥杯单片机组】两种外设访问方式:IO编程和MM编程

微信搜索&#xff1a;ReCclay&#xff0c;也可免费阅读博主蓝桥系列所有文章&#xff0c;后台回复“代码”即可获取蓝桥所有备赛代码&#xff01;关注博主公众号&#xff0c;还可拥有加入博主粉丝群实时沟通技术难题、免费下载CSDN资源等多项福利&#xff0c;还在等什么呢&…

树莓派——9、IO操控代码编程

编写操控io的代码 关于树莓派的cpu型号&#xff1a; 使用pinout 使用cat /proc/cpuinfo 查阅资料&#xff1a; 查阅资料发现树莓派3b的CPU型号就是BCM2709&#xff0c;也就是pinout中的BCM2827 要先确定IO空间的起始地址&#xff08;物理地址&#xff09; ps&#xff1a;树莓…

PHP并发IO编程之路

并发IO问题一直是服务器端编程中的技术难题&#xff0c;从最早的同步阻塞直接Fork进程&#xff0c;到Worker进程池/线程池&#xff0c;到现在的异步IO、协程。PHP程序员因为有强大的LAMP框架&#xff0c;对这类底层方面的知识知之甚少&#xff0c;本文目的就是详细介绍PHP进行并…

几种 IO编程比较

参考&#xff1a; Netty权威指南第一版 Java 网络IO编程总结&#xff08;BIO、NIO、AIO均含完整实例代码&#xff09; 1. 传统的BIO模型 通常由一个独立的Acceptor线程负责监听客户端的连接&#xff0c;它接收到客户端连接请求之后为每个客户端创建一个新的线程进行处理&am…

Java实验报告(七)|IO编程

文章目录 题目一题目二题目三 题目一 &#xff08;一&#xff09;编程实现打印目录“C:/”下所有后缀为“.txt”文件名。 import java.io.File; import java.util.Scanner; public class ShowTxt {public static void main(String[] args) {System.out.println("请输入要…

Linux下C语言编程(1):IO编程

笔者今天来讲讲Linux下IO口的使用。用的硬件是三大开源器件之一的BeagleBone&#xff08;狗骨头&#xff09;。 &#xff08;PS 三大开源器件&#xff1a;树莓派、Arduino和Beagle Bone&#xff09; 硬件介绍 TI公司的AM3358 集成 1G MHz ARM Cortex™ A8 内核&#xff0c; 4G…

IO接口编程

IO接口编程 作者&#xff1a; Saint 掘金&#xff1a;https://juejin.im/user/5aa1f89b6fb9a028bb18966a 微博&#xff1a;https://weibo.com/5458277467/profile?topnav1&wvr6&is_all1 GitHub&#xff1a;github.com/saint-000 CSDN: https://me.csdn.net/qq_405319…

网络编程IO

文章目录 前言用户空间和内核空间系统调用一、同步IO模型1、阻塞式IO模型2、非阻塞式IO模型3、IO复用模型4、信号驱动IO模型 二、异步IO模型三、同步和异步 前言 IO操作由两个部分组成&#xff1a;发起IO请求、实际进行IO操作。 也就是下图所示的等待数据从磁盘拷贝到内核空间…

Linux 下文件IO编程进程控制实验

Linux 下文件IO编程&进程控制实验 一、基本I/O操作 (1).Linux的输入/输出&#xff08;I/O&#xff09;操作&#xff0c;通常为五个方面&#xff1a;打开&#xff0c;读取&#xff0c;写入&#xff0c;定位和关闭&#xff1b;对应的函数分别为&#xff1a;open&#xff08;…

文件IO(IO编程)

一、文件IO&#xff08;IO编程&#xff09; 系统IO&#xff1a;和系统有关的IO接口函数 标准IO: 标准库里面的IO接口函数 #include <stdio.h> 目录操作&#xff1a;操作目录相关的IO接口函数 LCD屏的操作&#xff1a;刷图 TS(touch screen)触摸屏的操作:点击、滑动 二、…

I/O编程

一、标准IO 1.1、概述 标准IO 是ANSI C提供的函数接口&#xff0c;在文件IO的基础上封装出来的。任何兼容标准C库的操作系统都可以使用接口&#xff0c;具有更好的移植性。标准IO在执行时也会用到系统调用&#xff0c;为了增加内核的工作效率&#xff0c;减少资源浪费&#…

小米平板2装win10(附驱动)

前段时间在折腾着怎么给米pad2装win10&#xff0c;结果驱动什么的折腾了好久。 给米pad2装win10&#xff0c;其实就和给普通的电脑装win10差不多的步骤。 第一步&#xff0c;制作U盘启动器。工具什么的就用官方的winPE就好&#xff0c;iso就随意吧。 第二步&#xff0c;给米…

小米笔记本系统win10家庭版升级为企业版(专业版)

一.背景 新入职一家IT公司,由于公司领导层是小米粉,基本新入职的员工人手一本小米笔记本.小米笔记本默认自带的是家庭版的,由于之前公司很多人用的都是家庭版的,在某些极为特殊的软件开发情况下,家庭版的配置给开发带来了极大的困难,后来经过查资料验证企业版是不会出现这种情…

小米mix2s刷win11和android双系统

在给电脑安装系统的过程中&#xff0c;可能会因为各种原因出现windows无法安装的情况&#xff0c;我在给小米mix2s安装win11时发现出现了“计算机意外地重新启动或遇到错误&#xff0c;windows无法安装”的情况&#xff0c;下面就来教一下大家两种解决方法&#xff0c;希望可以…

小米air13.3一代的win10系统重装

仅作为记录&#xff0c;大佬请跳过 小米air的系统重装在进入bios之后&#xff0c;选择u盘启动时&#xff08;需要设置一个密码&#xff0c;然后关闭secure boot&#xff09;有点跟神船不一样&#xff0c;作为记录。 参考大佬博主文章传送门

Win10 IPv6 远程桌面连接(小米路由器)

前排广告&#xff1a;2021金三银四&#xff0c;字节跳动招人季&#xff0c;平均反馈时间仅1天&#xff01;选择覆盖达6大城市&#xff01;——2021年字节跳动飞书团队内推活动正式开启&#xff0c;岗位列表见&#xff1a;https://job.toutiao.com/s/eNtDcGu。除了这个投递连接外…

小米4A千兆刷OpenWrt_Win10

在Linux上试了一下&#xff0c;最终telnet 196.168.31.1失败&#xff0c;网上找了一些教程&#xff0c;改到win10下刷成功了。 1 先安装Pthon3 和pip3&#xff0c;然后pip3 install requests&#xff0c;不然会报错 2 win10开启telnet&#xff0c;方法简单自行百度&#xff1…

小米平板2可以装鸿蒙系统,详细教程!教你小米平板2轻松刷Win10

众所周知&#xff0c;小米平板2拥有MIUI和Windows 10两个版本&#xff0c;这两个版本在硬件上是一致的(除了机身存储空间不同)&#xff0c;所以理论上存在通刷的可能。 现在&#xff0c;有网友在MIUI论坛中共享了小米平板2刷Windows 10的教程&#xff0c;有兴趣的不妨一起来看看…

win10 下载

win10 下载 https://www.microsoft.com/zh-cn/software-download/windows10 Windows 10 2022 更新 l 版本 22H2 选择版本 以下 Windows 10 版本对于 Windows 10 家庭版和 Windows 10 专业版都有效。 如果您想验证下载数据的完整性和真实性&#xff0c;请按照以下步骤操作&…

计算机连接小米usb驱动,win10系统安装小米usb驱动的详细步骤

随着电脑的使用率越来越高&#xff0c;我们有时候可能会遇到对win10系统安装小米usb驱动进行设置&#xff0c;如果我们需要对win7系统安装小米usb驱动进行设置时&#xff0c;要怎么处理win10系统安装小米usb驱动的设置方法非常简单。 设置方法&#xff1a; 1、首先先下载小米驱…