c/c++ 学习总结(7)-- 标准库中IO缓冲区

c/c++语言把输入输出的功能从语言分离出来,通过标准库实现。记得在初学c语言时,书上说“stdin,stdout,stderr是c语言标准IO流,stdin负责从终端读入,stdout,stderr负责把信息输出到终端,其中stderr用于处理错误信息”,当时,看到这里我就在想,同样是把信息输出到终端,什么需要专门提供一个处理错误的“stderr”来?这个问题直到我学习过标准库的IO缓冲区之后才明白…


我们平时使用的stdio.h头文件中声明的函数,其实是在Linux的系统调用基础上封装的函数,它们相对系统调用的最大区别是:它们拥有每个进程私有的缓冲区。缓存分为3中:无缓冲,行缓冲,块缓冲。

  1. 无缓冲:使用fopen(3)函数返回的IO流,写端只要有数据进去,读端就能读到。默认情况下,连接到终端的stderr是无缓冲的,无缓冲意味数据会立即显示在终端。
  2. 行缓冲:使用fopen(3)函数返回的IO流,写端写入的数据需要等到缓冲区填满或者遇到换行符或者用fflush(3)强制冲洗缓冲区,读端才能读到。默认情况下,连接到终端的stdout是行缓冲的。
  3. 块缓冲:使用fopen(3)函数打开文件时,就采用的是块缓冲,事先用malloc分配一块空间,把数据先放到这块空间上,当空间填满后或调用fflush(3)才会把数据写到文件上。

看下测试代码:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>

FILE *p = NULL;
void  fun(int n){
        fflush(p);
        fclose(p);
        exit(0);
}

int main(){

        p = fopen("./temp.txt", "w");     //fopen打开文件,默认是块缓冲的
		
		//setbuf(p,NULL);                 //setbuf设置p为无缓冲,第一次测试时先注释掉
		
        signal(SIGQUIT,fun);             //安装信号处理函数,当按下"ctrl + \"时捕获SIGQUIT信号
        if(p == NULL){     //文件没打开就退出
                printf("文件打开失败\n");
                exit(0);
        }
        while(1){            //不停的向文件写入1
                sleep(1);    //如果不sleep下,块缓冲区很快就填满了,看不到测试效果   
                fwrite("1",2,1,p);
        }
        fclose(p);
        return 0;
}

说明下,第一次测试时把"setbuf(p,NULL);"注释掉,当程序运行起来后,在重新开启一个终端,使用命令“tail -f temp.txt”观察文件,发现什么也没有,原因是采用的块缓冲,需要当缓冲区填满后才会真正的把数据写入文件中;当按下“ctrl + \”时,回调信号处理函数,在处理函数中会使用fflush冲洗块缓冲把数据写入文件中;第二次测试时把"setbuf(p,NULL);"打开,运行程序,再次用命令“tail -f temp.txt”观察文件,发现有数据“1”输出。

总结:

  1. 缓存区是每个进程私有的;
  2. 通常我们说“标准IO是带有缓冲区”,而linux系统调用是“不带有缓冲区”的,其实严格来说系统调用也是有缓冲区,但这个缓冲区是在内核中,是进程共享的,使用write(2),read(2)等底层函数时,它们的返回值是一个int类型的文件描述符,当这个内核中缓存准备好了,我们就会说“文件描述符就绪了”。

再说个题外话:认识到内核中缓存区是很重要的,因为对于“同步与异步”,“阻塞与非阻塞”,“为什么采用内存文件映射方式处理大文件会比使用read(2)效率高”等问题,不了解内存中缓冲区就很难理解了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值