Printf的缓冲机制

转:https://blog.csdn.net/qq_25424545/article/details/78772959

今天用fork()写程序时候,突然发现自己对Printf的缓冲机制还是有些不够了解,于是来深度解析一下,Printf的缓冲机制到底是怎么一回事呢?

首先printf是库函数,它是由C标准库提供的,它是对系统调用函数write()的一层封装,既然是封装,那它就一定会有改进和性能上的提升,达到方便使用的目的,缓冲机制就是其中的一项改进。为了更加透彻的了解printf函数的缓冲机制,我们来看下面的两个例子。

运行环境:gcc (GCC) 4.4.7

代码1:

#include<stdio.h>
#include<unistd.h>
int main()
{
printf("hehe\n");
int ret = fork();
if(ret==0)
{
//child
printf("I am child\n");
}
else if(ret<0)
{
printf("Error\n");
}
else
{
printf("I am father\n");
}

return 0;
}
运行结果1:

hehe
I am father
I am child

代码2:

#include<stdio.h>
#include<unistd.h>
int main()
{
printf("hehe");
int ret = fork();
if(ret==0)
{
//child
printf("I am child\n");
}
else if(ret<0)
{
printf("Error\n");
}
else
{
printf("I am father\n");
}

return 0;
}
运行结果2:

heheI am father
heheI am child

相信聪明的你可以看出这两个代码块唯一不同之处在与两个代码开头处的printf,第一个带了\n,第二个并没有带,然而输出结果确实大不相同,究其原因在于printf函数缓冲机制,printf函数实际上只是输出到了标准输出缓冲队列上,并没有实实在在的打印到屏幕上,标准输出是行缓冲机制,也就是说,遇到\n,就会刷新缓冲区,输出到屏幕上,在第一个程序中fork之前已经输出,并刷新了缓冲区,因此子进程不会会继承父进程的这个内容,而在第二个程序中,由于没有遇到换行符,所以字符串"hehe"还在缓冲区中,这时子进程的缓冲区里有也有了这个字符串,所有第二个程序会多打印个"hehe"

内核的缓存是在驱动做的,所有调用printf的程序都共享,但是在应用层的c库也做了缓存,这部分缓存是程序独立的

拓展:

行缓冲:见到‘\n‘刷新缓冲区(例如stdout)

全缓冲:见到‘\n‘不刷新,直到显示fflush()、缓冲区满或者退出才会刷新缓冲区(例如输出文件)
---------------------
作者:T_tangc
来源:CSDN
原文:https://blog.csdn.net/qq_25424545/article/details/78772959
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/newjiang/p/10711892.html

时间: 2024-08-02 12:31:23

Printf的缓冲机制的相关文章

位图操作和双缓冲机制

位图操作代码部分: CRect rect;  GetClientRect(rect);  pDC->SetMapMode(MM_ANISOTROPIC);  pDC->SetWindowExt(rect.Width(), rect.Height());  pDC->SetViewportExt(rect.Width(), -rect.Height());  pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2); CDC MemDC

VC GDI双缓冲机制绘图防屏幕闪烁实现步骤

在OnDraw(CDC* pDC) 中添加如下代码 CDC MemDC; //首先定义一个显示设备对象 CBitmap MemBitmap;//定义一个位图对象 //随后建立与屏幕显示兼容的内存显示设备 MemDC.CreateCompatibleDC(NULL); //这时还不能绘图,因为没有地方画 ^_^ //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小,也可以自己定义(如:有滚动条时就要大于当前窗口的大小,在BitBlt时决定拷贝内存的哪部分到屏幕上) MemBit

java : 包装类 缓冲机制的使用(转载)

摘要: 八种基本数据类型和其包装类中 Integer valueOf(int i).Byte valueOf(byte b).Short valueOf(short s).Long valueOf(long l).Character valueOf(char c)都是用到了缓冲机制,并且缓冲的范围都是-128~127 但是,对于包装类Float,Double,Boolean 并没有提供相应的缓冲机制 为了了解缓冲机制的使用,我们先从Integer 与 int的互转入手: JDK1.5为Integ

双缓冲机制简介

一.理解双缓冲机制 1.创建一个画板,和一个图片() 2.将图片设置为画板 3.之后画板将会在该图片上作画 4.之后再将图片放到View提供的画板上显示 二.实例(利用双缓冲机制的画板) public class DrawView extends View { private int view_width = 0; private int view_height = 0; private float prevX = 0; private float prevY = 0; private Path

GO语言练习:channel 缓冲机制

1.代码 2.运行 3.解析 1.代码 buffer.go 1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 func readThread(ch chan int) { 9 fmt.Println("read for reading...") 10 for i := range ch { 11 fmt.Println("get i : ", i) 12 if 20 ==

fgetc read缓冲机制区别

read属于系统调用,它的缓存是基于内核的缓冲,是记在内核空间的. 而fgetc是标准函数, 是在用户空间I/O缓冲区的 比如用fgetc读一个字节,fgetc有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE结构体中记录的读写位置是1. 所以如果read一次读取的缓冲大小是1个字节,则1K的文件,read需要调1024次系统调用.而同样是一次只读一个字节,fgetc只调用一次系统调用. fgetc read缓冲机制区别

MySQL数据库的查询缓冲机制

MySQL数据库的查询缓冲机制 2011-08-10 11:07 佚名 火魔网 字号:T | T 使用查询缓冲机制,可以极大地提高MySQL数据库查询的效率,节省查询所用的时间.那么查询缓冲机制是怎样设置的呢?本文我们就来介绍这部分内容,希望能够对您有所帮助. AD: MySQL数据库提供了查询缓冲机制.使用该查询缓冲机 制,MySQL将SELECT语句和查询结果存放在缓冲区中,以后对于同样的SELECT语句(区分大小写),将直接从缓冲区中读取结果.以节省查询时 间,提高了SQL查询的效率.本文

web缓冲机制

最近项目里用到了Html5缓存机制,于是很想搞清楚 浏览器缓存,HTML5离线缓存,还有项目中用到的 CDN缓存 这三部分的关系以及更新机制.看了一堆关于HTML5缓存机制的文章,各有所长,各有疏漏.因此本人想在此做一总结,本文假设读者对基本的HTML5缓存应用已有所了解,因此不再详述概念,可以将本文当做释疑汇总吧. 以下部分内容引用自网络. 一.Web缓存的类型 在Web应用领域,Web缓存大致可以分为以下几种类型: 数据库数据缓存 Web应用,特别是SNS类型的应用,往往关系比较复杂,数据库

安卓View的缓冲机制

View组件显示的内容能够通过cache机制保存为bitmap, 主要有下面方法: void  setDrawingCacheEnabled(boolean flag),  Bitmap  getDrawingCache(boolean autoScale),  void  buildDrawingCache(boolean autoScale),  void  destroyDrawingCache() 我们要获取cache首先要通过setDrawingCacheEnable方法开启cache