不管是操作系统,还是学语言,大家应该都听过缓冲区,那么什么是缓冲区?缓冲区又位于什么地方?在这篇文章,小编将带你了解缓冲区。❄️❄️❄️先让我们欣赏下面的一张图,让我们恭僖EDG夺得冠军。❄️❄️❄️

缓冲区

  • 1、缓冲区的引出
    • 1.1 “\n”
    • 1.2 fflush
  • 2、缓冲方案
  • 3、缓冲区的提供者
    • 3.1 通过代码观察现象
    • 3.2 结果分析和原因剖析
    • 3.3 结论
  • 4、内核缓冲区

1、缓冲区的引出

1.1 “\n”

  对于下面的代码,他们的执行结果会是怎样的呢?

int main()
{printf("你好呀,缓冲区!\n");sleep(3);return 0;
}
int main()
{printf("你好呀,缓冲区!");sleep(3);return 0;
}

  两个代码都是打印“你好呀,缓冲区!”,然后sleep 3s,但是唯一不同的是,代码1在打印内容后有一个“\n”的换行,而代码2是没有的,这小小的一个符号,会让我们的结果产生怎样的不同呢?
代码1运行结果如图:先打印字符串,然后休眠3s

代码2运行结果如图:先休眠3s,然后打印字符串

  通过上面的结果,我们能不能得出两个代码的执行顺序不一样的结论呢?答案是否定的! 不管代码怎么变化,代码都是自上而下依次执行,只不过没有\n时,你好呀,缓冲区!会先被保存在缓冲区中,所以运行时先sleep然后打印,给人的结果像是先执行sleep,其实不是的。其实printf先执行完了,只不过数据并没有被立马显示出来,运行结束后才显示出来,说明printf执行完后将hello world先保存在了缓冲区中。由此引出了缓冲区的概念。

1.2 fflush

  相信读者都了解文件描述符和重定向的相关知识,如果对这方面不了解的读者可以查看小编的另一篇文章《文件描述符》。我们知道,对于下面的代码,当我们直接运行的时候,无论是显示器还是log.txt中都没有对应的数据。其结果如下:

int main()
{close(1);umask(0);int fd = open("log.txt",O_WRONLY|O_CREAT, 0666);if(fd<0){perror("open file!\n");return 1;}printf("你好呀,缓冲区!\n");                                                                                                                                               close(fd);return 0;
}

  这是为什么呢?这里的数据仍然是在缓冲区中保存的,我们必须要调用fflush,才能将数据刷新到log.txt文件中。

int main()
{close(1);umask(0);int fd = open("log.txt",O_WRONLY|O_CREAT, 0666);if(fd<0){perror("open file!\n");return 1;}printf("你好呀,缓冲区!\n");     fflush(stdout);                                                                                                                                          close(fd);return 0;
}


2、缓冲方案

  一般情况下,缓冲/刷新方案分为三种:a.无缓冲;b.行缓冲(常见的对显示器进行刷新数据时);c.全缓冲(对文件写入的时候采用的是全缓冲,这里的文件可以理解为磁盘文件)。

  说白了就是在计算机内存中提供了一块内存空间,不断地往空间中写入数据,当行缓冲满了,或者写入了\n,他会把一行或者包括\n在内的所有内容全部刷新出来。如果没有+\n,但是也想要他刷新就要加fflush(stdout),就会将缓冲区的内容刷新出来;全缓冲就是这块缓冲区必须满了才会刷新到对应的磁盘中去。
  那么为什么显示器是行缓冲,而文件写入是全缓冲呢?因为计算机遵循的是冯诺依曼体系,像文件这样的其实是属于外设,或者外设之上,比如键盘是外设,磁盘是外设,换句话说我们要把数据刷新到磁盘或者显示器上都叫做往外设中写入,外设的写入效率是很低的,所以我们把数据积累到内存缓冲区中,当积累的足够多的时候定期刷新,提高效率。
  按照这说法,那是不是全缓冲效率最高,答案是对的!!!理论上全缓冲效率确实是最高的,那为什么显示器还要再进行行缓冲呢?可以这样理解,磁盘在文件写入的时候人是不会读的,显示器不一样,当一个人往显示器上写入数据的时候,他是想尽快拿到对应的输出结果,如果选择无缓冲,效率就会很低,全缓冲人看到消息就不及时,所以设置为行缓冲。所谓行缓冲就是在效率和可用性做的平衡。

3、缓冲区的提供者

3.1 通过代码观察现象

  为了理清这些问题,我们写一份代码让大家看一下奇怪的现象。下面这份代码是分别调用C库函数接口和系统调用接口打印三行代码,结果也是没有问题的打印到显示器中,我们./test>log.txt,将结果进行重定向,也是正确的。

int main()
{//C语言库函数接口printf("hello printf!\n");rprintf(stdout, "hello rprintf!\n");//系统调用接口const char* str = "hello wirte!\n";write(1 str, strlen(str));return 0;
}

  修改代码,我们在最后加一个fork,fork是在三行打印代码之后,所以fork并不会影响其他函数,此时结果仍是对的,但是我们输出到log.txt就有问题了。

int main()
{//C语言库函数接口printf("hello printf!\n");rprintf(stdout, "hello rprintf!\n");//系统调用接口const char* str = "hello wirte!\n";write(1 str, strlen(str));fork();//添加了一个fork函数,生成子进程return 0;
}

3.2 结果分析和原因剖析

结果分析: 我们往显示器上打,结果是3行,显示器采用的是行缓冲;如果重定向到文件里,此时缓冲方式发生了变化,成了全缓冲,而且在往文件中打印的时候,hello printf和hello fprintf打印了两次,hello write只打印了依次一次。根据上面的结果,我们得出结论:(1.重定向还是不重定向会更改进程的缓冲方式;(2.C接口打了两次,系统调用接口打印了一次。

原因剖析: fork是在程序的最后,根据程序自上而下执行的原理,当执行到fork的时候三个打印函数确实已经执行完了,但是有没有全部刷新呢?有没有全部显示呢?-答案是不一定。当你是往显示器上打印的时候,因为他是行刷新,并且都带了\n,所以三个打印函数都完成了打印&&刷新的工作;当你把程序运行起来重定向到log.txt中时,刷新方式变成了全缓冲,C语言的两个库函数仅仅完成了打印功能,内容还是在缓冲区中,没有刷新,即hello printf和hello fprintf只是打印在了缓冲区,并没有显示出来,当执行到fork的时候,这个缓冲区是是父进程中的一块内存区域,里面保存了当前进程的数据,所以当你fork的时候,后续完成之后,父子进程都要进行数据刷新,因为程序退出时,该缓冲区内存区域就要被刷新了,当父子进程各自进行刷新时,因进程具有独立性,不管父子进程谁先刷新缓冲区,一旦一个进程刷新了缓冲区,刷新缓冲区本质就是修改缓冲区数据,此时就要发生写时拷贝,所以C语言的库函数打印了两次,因为a.缓冲区的存在;b.发生了写时拷贝!
  那为什么系统的接口write没有打印两次呢? 说明write没有缓冲区!!

3.3 结论

  如果缓冲区是操作系统提供的,绝对所有的接口都要打印两次。所以这个缓冲区是C语言自带的!所以我们通常所说的缓冲区是语言自带的缓冲区。所有的缓冲区都在内存,只不过问题是这个内存谁申请的,这个缓冲区是在内存的内核区还是内存的用户区。

4、内核缓冲区

  我们前面学的是C语言提供的缓冲区,但是缓冲区不止这一个,还有其他的。内存分为用户区和内核区,操作系统是软硬件资源的管理者,我们不可能直接将FILE里面的缓冲区的内容直接刷新到磁盘和显示器中,而是要经过操作系统,所以在内核区还有一个属于操作系统级别的缓冲区,这个缓冲区有自己的刷新机制,会往磁盘和显示器这样的外设刷新缓冲区内容,用户里面的缓冲区内容是往内核中的缓冲区刷新的,我们不需要关心内核中的缓冲区刷新策略。

搞懂缓冲区,看这篇文章就够了相关推荐

  1. PID算法搞不懂?看这篇文章就够了。

    点击上方"大鱼机器人",选择"置顶/星标公众号" 福利干货,第一时间送达! 转自知乎: jason 原文链接:https://zhuanlan.zhihu.co ...

  2. 【转载】搞懂PointNet++,这篇文章就够了!

    论文标题:PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space 1 motivation 从名字 ...

  3. 使用分层网络模型的两个优点是什么_从零开始学网络|搞懂OSI参考模型和TCP/IP分层模型,看这篇文章就够了...

    从零开始学网络|搞懂OSI参考模型和TCP/IP分层模型,看这篇文章就够了​mp.weixin.qq.com 前言 今天和大家一起谈谈"网络",之前写的文章可能不太通俗易懂,有人就 ...

  4. C++两个函数可以相互递归吗_[算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进

    [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...

  5. [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进

    [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进 从学习写代码伊始, 总有个坎不好迈过去, 那就是遇上一些有关递归的东西时, 看着简短的代码, 怎么稀里糊涂就出来了. ...

  6. 万字心得,PMP学习考试那些事儿,看这篇文章就够了

    声明:文章为原创,首发于知乎,链接:万字长文!PMP考试那些事儿,看这篇文章就够了 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/524966002 以下内 ...

  7. 斗鱼html5插件音画不同步,音画不同步在直播中怎么解决?看这篇文章就够了!...

    原标题:音画不同步在直播中怎么解决?看这篇文章就够了! 什么是音画不同步? 很容易判断,就是画面和声音不匹配. 为什么会音画不同步? 首先我们要明白一个概念,虽然人的肉眼很容易辨别音画是否同步的,但是 ...

  8. Python-Excel 零基础学习xlwings,看这篇文章就够了

    零基础学习xlwings,看这篇文章就够了 | 一起大数据-技术文章心得 (17bigdata.com) 1.xlwings是什么 2.xlwings安装更新与卸载 3.xlwings详细使用 4.案 ...

  9. Vue开发入门看这篇文章就够了

    摘要: 很多值得了解的细节. 原文:Vue开发看这篇文章就够了 作者:Random Fundebug经授权转载,版权归原作者所有. 介绍 Vue 中文网 Vue github Vue.js 是一套构建 ...

  10. Android 8.0新特性(看这篇文章就够了)

    2019独角兽企业重金招聘Python工程师标准>>> 在刚结束不久的谷歌 I/O2017开发者大会上发布的第二个Android O(安卓8.0)开发者预览,并且向普通用户开放了第二 ...

最新文章

  1. RMB77元实现全身VR跟踪,来自配合微软Kinect的Driver4VR
  2. 【jquery】ajax 请求成功后新开窗口被拦截解决方法
  3. LeetCode 300. 最长上升子序列(Longest Increasing Subsequence)
  4. OpenCV形态学变换函数morphologyEx()梯度运算的使用
  5. Linux下判断cpu物理个数、几核
  6. C++之return的作用域
  7. Mozart Update 1(杯具额…)
  8. C#-is and as
  9. 【正点原子MP157连载】 第二十二章 ADC实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南
  10. zooInspector下载
  11. 菜鸟学运筹学----引
  12. JSON.Stringify
  13. 风险预测模型_5分+整合多中心临床样本构建5分子胰腺癌预后模型
  14. B站风清扬-Java面试总结
  15. php面试时的自我称呼,PHP程序员面试自我介绍
  16. android 模拟器 itools,iTools安卓模拟器常见问题及解决方法
  17. 2022CCF中国软件大会(CCF ChinaSoft)“系统软件教育”论坛成功召开
  18. ubuntu18.04 cuda卸载及安装
  19. 一看就会一学就废之SpringBoot整合通用Mapper以及常用方法
  20. 【python】Matplotlib作图常用marker类型、线型和颜色

热门文章

  1. 戳进来!领取你的专属「星巴克」微信状态~
  2. 日志冲突怎么解决?slf4j和log4j的区别?看完这一篇,这些都是小意思啦
  3. 人脸识别有趣应用2——自动增大眼睛效果
  4. BAT大牛亲授基于ElasticSearch的搜房网实战(第四章环系统架构设计与分层)
  5. Simulink求解器综合介绍
  6. 教你一招破解字节码加密
  7. 投影机使用需要了解哪些知识?
  8. English--并列句
  9. pbootcms34套企业网站模板源码打包
  10. Base64与BLOB互相转换