Linux文件:缓冲区、缓冲区刷新机制 | C库模拟实现

一、缓冲区的作用

 缓冲区本质上就是一部分内存,用于提高效率!!

 对于文件的IO等操作,用户可以直接通过系统调用直接向操作系统进行读操作和写操作。但这样时间开销较大。所以在语言层面一般会维护一段语言级别的缓冲区,用于暂存数据。我们可以快速向缓冲区中写入数据,然后通过一定的刷新方式。将数据从语言级别的缓冲区中拷贝到内核缓冲区。大大提高使用者的效率!!

&mesp;同时由于缓冲区的存在,我们可以积累一定的数据后在统一发生,提高发送的效率!!

二、缓冲区的刷新机制

 缓冲区可以暂存数据,必定存在一定的刷新机制。常见的刷新机制由以下3种:

  1. 无缓冲(立即刷新)
  2. 行缓冲(行刷新)
  3. 全缓冲(缓冲区全部写满后在刷新)

其中显示器文件的刷新机制就是行刷新;对于磁盘上的文件则是全缓冲!!

除此之外,还存在一些特殊的刷新机制:

  • 强制刷新。比如调用flush函数,以及printf在执行时,碰到/n时强制刷新!
  • 进程退出时,一般会刷新缓冲区!

三、测试样例解析

3.1 测试样例和运行结果

 下面我们调用3个常见的C库函数和一个系统调用,都向显示器文件中进行写入。当写入操作完毕后创建子进程,我们来看看分别向显示器文件磁盘文件中进行写入会发生什么?

int main()    
{
       
    fprintf(stdout, "C: hello fprintf\n");    
    printf("C: hello printf\n");                                          
    fputs("C: hello fputs\n", stdout);    
    const char* buf = "system call: hello write\n";    
    write(1, buf, strlen(buf));    
    fork();    
    return 0;    
} 

 我们编译后,直接运行向显示器写入。然后通过输出重定向向log.txt磁盘文件进行写入:

【运行结果】:

在这里插入图片描述

3.2 结果分析

1、向显示器文件写入:

 当我们直接向显示器打印消息时,由于显示器的刷新机制是行刷新;并且我们所打印的字符串都带了‘\n(在printf中,'\n'是一种强制刷新的触发机制)。所以在fork()创建子进程前,数据已经全部被刷新!!

2、向磁盘文件进行写入:

 当我们重定向向磁盘文件写入数据时,缓冲区的刷新机制由行缓冲变成全缓冲。全缓冲也就意味着缓冲区变大,简单的几个字符串不足以将缓冲区写满,无法触发刷新机制

 此时缓冲数据还在缓冲区但当前缓冲区为C语言所提供的缓冲区,和操作系统无关。所以当前缓冲区中的数据依然属于进程。当fork()创建完子进程退出时,一般会刷新缓冲区。

 而刷新缓冲区本质上也是一种清空或者写入操作。所以父进程和子进程在退出前数据共享同一份;当退出时刷新缓冲区,对数据进行修改会发生写时拷贝,父、子进程各自私有一份。所以最后对于C函数调用会存在两份!!

 至于系统调用数据只打印一份的原因在于:系统调用在语言之下,数据不是向语言基本的缓冲区中写入;而是直接向操作系统内核缓冲区中写入。此时数据属于操作系统,不在属于进程!!

四、语言级别的缓冲区究竟在哪?

 下面我们以C为例。

 在此时样例中,我们已经知道对于库函数printf、fprintf自带缓冲区,而系统调用write则没有。(内核提提供的缓冲区此处不考虑)库函数时对系统调用的封装,这也意味着C所提供的缓冲区是二次加上的,由C本身所提供!!

 在C中,所有的IO函数都存在一个FILE指针,或者底层会封装FILE指针。而C的缓冲区的相关信息则保存在FILE结构体中,由FILE结构体来维护!!

FILE结构体内容】:
 在/usr/include/stdio.h路径下,存在这样一段代码typedef struct _IO_FILE FILE。所以可以通过下面操作查找FILE:
在这里插入图片描述

FILE结构体】:

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

 
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白debug~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值