【Linux系统编程】IO标准缓冲区

简介: 【Linux系统编程】IO标准缓冲区

1. 缓冲区概述

标准I/O提供了三种类型的缓冲:


1、全缓冲:


在填满标准I/O缓冲区后才进行实际I/O操作。常规文件(如普通文本文件)通常是全缓冲的。


2、行缓冲:


当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符,但只有在写了一行之后才进行实际I/O操作。标准输入和标准输出对应终端设备(如屏幕)时通常是行缓冲的。


3、不带缓冲:


用户程序每次调库函数做写操作都要通过系统调用写回内核(如系统调用函数)。标准错误输出通常是无缓冲的,这样用户程序产生的错误信息可以尽快输出到设备。

2. 全缓冲

测试代码:

int main(int argc, char *argv[])
{
  FILE *fp = NULL;
  // 读写方式打开,文件不存在则创建
  fp = fopen("test.txt", "w+");
  if(NULL == fp)
  {
    printf("open error\n");
    return 1;
  }
  char *str = "C++程序员\n";
  fwrite(str, 1, strlen(str), fp);  // 往文件写内容
  while(1); // 程序阻塞在这里
  return 0;
}

运行程序发现,test.txt并没有内容。因为常规文件通常是全缓冲的,只有缓冲区满了后,才会把内容写到文件中。接下来,我们改一下上面那个例子。


测试代码:

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
  FILE *fp = NULL;
  // 读写方式打开,文件不存在则创建
  fp = fopen("test.txt", "w+");
  if(NULL == fp)
  {
    printf("open error\n");
    return 1;
  }
  char *str = "test\n";
  int i = 0;
  while(i <= 512){  // 缓冲区大小不确定,i的大小只是一个调试值
    fwrite(str, 1, strlen(str), fp);  // 往文件写内容
    i++;
  }
  while(1); // 程序阻塞在这里
  return 0;
}

上面的例子是循环给文件写内容,让缓冲区有填满的可能,结果发现,文件是有内容的。实际上要想成功给文件写进内容,除了缓冲区填满,还有别的方法。


2.1 人为关闭文件,就算缓冲区没有填满,内容也会写进文件

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
  FILE *fp = NULL;
  // 读写方式打开,文件不存在则创建
  fp = fopen("test.txt", "w+");
  if(NULL == fp)
  {
    printf("open error\n");
    return 1;
  }
  char *str = "test ok\n";
  fwrite(str, 1, strlen(str), fp);  // 往文件写内容
  fclose(fp);   // 人为关闭文件,就算缓冲区没有填满,内容也会写进文件
  while(1); // 程序阻塞在这里
  return 0;
}

2.2 程序正常结束,就算缓冲区没有填满,没有关闭文件,内容也会写进文件。

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
  FILE *fp = NULL;
  // 读写方式打开,文件不存在则创建
  fp = fopen("test.txt", "w+");
  if(NULL == fp)
  {
    printf("open error\n");
    return 1;
  }
  char *str = "test ok\n";
  fwrite(str, 1, strlen(str), fp);  // 往文件写内容
  return 0;
  // 程序正常结束,就算缓冲区没有填满,没有关闭文件,内容也会写进文件。
}

3. 行缓冲

#include <stdio.h>
int main(int argc, char *argv[])
{
  printf("hello test");
  while(1);
  return 0;
}

运行这个程序,会发现 hello test并没有打印到屏幕上。因为标准输入和标准输出对应终端设备时通常是行缓冲的,当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。如下:

#include <stdio.h>
int main(int argc, char *argv[])
{
  printf("hello test\n");
  while(1);
  return 0;
}

除了遇到换行符,还有别的方法可以执行I/O操作。


3.1 缓冲区满

int main(int argc, char *argv[])
{
  while(1)
    { 
        // 循环打印,总有缓冲区填满的可能
    printf("hello sunplusedu");
  }
  while(1);
  return 0;
}

3.2 人为刷新缓冲区

#include <stdio.h>
int main(int argc, char *argv[])
{
  printf("hello test");
  fflush(stdout); // 人为刷新
  while(1);
  return 0;
}

3.3 程序正常结束

#include <stdio.h>
int main(int argc, char *argv[])
{
  printf("hello sunplusedu");
  return 0;
  // 程序正常结束
}

4. 不带缓冲区

#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
  char *str = "hello test"; 
  // 有没有\n,缓冲区有没有填满,都没关系
  write(1, str, strlen(str)); // 往标准输出写内容
  while(1);
  return 0;
}

Linux系统调用中的IO函数一般不带有缓冲区。

往期精彩

嵌入式系统软件架构设计(长篇深度好文)


专为MCU项目开发提速的代码框架BabyOS


嵌入式C语言代码优化方案(深度好文,建议花时间研读并收藏)


分享一个在Keil开发环境中配置代码格式化工具Astyle(美化代码风格)


stm32cubeMX学习、USB DFU(Download Firmware Update)固件更新

目录
相关文章
|
7月前
|
Ubuntu Linux Anolis
Linux系统禁用swap
本文介绍了在新版本Linux系统(如Ubuntu 20.04+、CentOS Stream、openEuler等)中禁用swap的两种方法。传统通过注释/etc/fstab中swap行的方式已失效,现需使用systemd管理swap.target服务或在/etc/fstab中添加noauto参数实现禁用。方法1通过屏蔽swap.target适用于新版系统,方法2通过修改fstab挂载选项更通用,兼容所有系统。
612 3
Linux系统禁用swap
|
7月前
|
Linux
Linux系统修改网卡名为eth0、eth1
在Linux系统中,可通过修改GRUB配置和创建Udev规则或使用systemd链接文件,将网卡名改为`eth0`、`eth1`等传统命名方式,适用于多种发行版并支持多网卡配置。
1143 3
|
Ubuntu Linux 网络安全
Linux系统初始化脚本
一款支持Rocky、CentOS、Ubuntu、Debian、openEuler等主流Linux发行版的系统初始化Shell脚本,涵盖网络配置、主机名设置、镜像源更换、安全加固等多项功能,适配单/双网卡环境,支持UEFI引导,提供多版本下载与持续更新。
716 3
Linux系统初始化脚本
|
8月前
|
运维 Linux 开发者
Linux系统中使用Python的ping3库进行网络连通性测试
以上步骤展示了如何利用 Python 的 `ping3` 库来检测网络连通性,并且提供了基本错误处理方法以确保程序能够优雅地处理各种意外情形。通过简洁明快、易读易懂、实操性强等特点使得该方法非常适合开发者或系统管理员快速集成至自动化工具链之内进行日常运维任务之需求满足。
544 18
|
7月前
|
安全 Linux Shell
Linux系统提权方式全面总结:从基础到高级攻防技术
本文全面总结Linux系统提权技术,涵盖权限体系、配置错误、漏洞利用、密码攻击等方法,帮助安全研究人员掌握攻防技术,提升系统防护能力。
822 1
|
7月前
|
监控 安全 Linux
Linux系统提权之计划任务(Cron Jobs)提权
在Linux系统中,计划任务(Cron Jobs)常用于定时执行脚本或命令。若配置不当,攻击者可利用其提权至root权限。常见漏洞包括可写的Cron脚本、目录、通配符注入及PATH变量劫持。攻击者通过修改脚本、创建恶意任务或注入命令实现提权。系统管理员应遵循最小权限原则、使用绝对路径、避免通配符、设置安全PATH并定期审计,以防范此类攻击。
1239 1
|
8月前
|
缓存 监控 Linux
Linux系统清理缓存(buff/cache)的有效方法。
总结而言,在大多数情形下你不必担心Linux中buffer与cache占用过多内存在影响到其他程序运行;因为当程序请求更多内存在没有足够可用资源时,Linux会自行调整其占有量。只有当你明确知道当前环境与需求并希望立即回收这部分资源给即将运行重负载任务之前才考虑上述方法去主动干预。
2142 10
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
6月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
265 1
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用

热门文章

最新文章