文件缓冲区在fork后复制
场景:父进程trace进程A,当A进程fork子进程B时,让父进程也fork子进程去trace子进程B,用于trace的进程将被trace的进程发生的系统调用号通过fprintf存入各自文件中
问题:printf输出正确,而fprintf到文件的内容会重复(其实就知道了是缓冲问题)
解决:在调用fork()前用fflush(fp);清空文件缓冲区
原因:在fork()的调用处,整个父进程空间会被复制到子进程中,包括指令,变量值,程序调用栈,环境变量,缓冲区,等等。
延伸到stdio缓冲区:stdio缓冲区在进程的用户空间内存中,通过fork()创建的子进程会复制这些缓冲区,当标准输出定向到终端时,因为缺省为行缓冲,所以会显示printf输出的包含换行符的字符串。
不过,当标准输出重定向到文件时,由于缺省块缓冲,所以调用fork()时,printf()输出的字符串仍然在父进程的缓冲区中,并随子进程的创建而产生一份副本。
父,子进程调用exit()时会刷新各自stdio缓冲区,从而导致重复输出的结果。
知识:
标准I/O库提供了三种类型的缓冲:
(1) 全缓冲:填满标准I/O缓冲区才实际进行I/O操作。
(2)行缓冲:在输入和输出中遇到换行符时,标准I/O库执行I/O操作,当流涉及终端时,通常使用行缓冲。
(3)不带缓冲:标准出错流stderr通常是不带缓冲的。
上面说的缓冲指的是应用层的缓冲,在进行实际的I/O操作时,相关的系统调用(read和write)其实在内核也有缓冲区的。
当输出到终端时,由于是行缓冲,所以遇到换行符'\n'后缓冲区被冲洗。
当将程序输出重定向到文件时,标准输出是全缓冲,fork之前printf的数据仍在缓冲区中,在fork时该缓冲区也被复制到子进程中,因此输出两次。
实验:
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h> int main()
{
FILE *fp = fopen("./1.txt", "wt+");
if(fp == NULL)
{
return -;
}
printf("xxx\n");
fprintf(fp, "%d\n", );
//fflush(fp);//调用fork()之前使用函数fflush()来刷新stdio缓冲区
if(!fork())
{
exit();
//_exit(0);//子进程调用_exit(0)而非exit()以不再刷新stdio缓冲区
} return ;
}
1、输出到终端(行缓冲)
2、重定向到文件xxx.txt(块缓冲)
3、fprintf到文件1.txt(fprintf函数在默认情况下只有当缓冲区达到一定条件或是程序自然停止时才会输出数据到文件)

可以看到2和3都重复输出,用上面注释的方法即可解决该问题
概念参考:
https://blog.csdn.net/dextrad_ihacker/article/details/52033223
http://www.cnblogs.com/tonychen-tobeTopCoder/p/5335452.html
文件缓冲区在fork后复制的更多相关文章
- fork后父子进程文件描述问题
[fork后父子进程文件描述问题] 一张图可以浅析的解释: 参考:http://wenku.baidu.com/view/dd51581bff00bed5b9f31d8e.html
- IOSerialize,xml和json,soap序列化器,二进制序列化器,XML序列化器,文件 检查、新增、复制、移动、删除
1 文件夹/文件 检查.新增.复制.移动.删除,2 文件读写,记录文本日志/读取配置文件3 三种序列化器4 xml和json1.文件夹/文件 检查.新增.复制.移动.删除,2 文件读写,记录文本日志/ ...
- IO流,字节流复制文件,字符流+缓冲复制文件
JAVAIO如果按流向分:输入流和输出流两种 输入流的基类:InputStream Reader 输出流的基类:OutputStream Writer 如果按数据单元划分:字节流和字符流 字节 ...
- github fork后的pull和保持同步
前言 对github上的某个项目贡献自己的修改,但自己可能并没有那个仓库的权限,那要如何操作呢?git的机制和svn还是有些区别的,本文做些记录. 思路1 clone项目到本地,有修改之后,直接提交到 ...
- Web 在线文件管理器学习笔记与总结(13)重命名文件夹(14)复制文件夹
(13)重命名文件夹 ① 重命名文件夹通过 rename($oldname,$newname) 实现 ② 检测文件夹名是否符合规范 ③ 检测当前目录中是否存在同名文件夹名称,如果不存在则重命名成功 i ...
- 每次调用fork()函数之后,父线程和创建出的子线程都是从fork()后开始执行
Linux下多少个"-"将被打印: 1 2 3 4 5 6 7 8 int main(void){ int i; for(i=0;i<4;i++){ fork() ...
- c# 封装的文件夹操作类之复制文件夹
c# 封装的文件夹操作类之复制文件夹 一.复制文件夹原理: 1.递归遍历文件夹 2.复制文件 二.FolderHelper.cs /// <summary> /// 文件夹操作类 /// ...
- 用winscp从本地上传文件到服务器上出现复制文件到远端时错误。
用winscp从本地上传文件到服务器上出现复制文件到远端时错误. 错误码:4 服务器返回的错误消息:write failed 报错如下图所示: 分析过程: 1.刚开始以为是权限不够,后面上网查了一下是 ...
- 将目录下面所有的 .cs 文件合并到一个 code.cs 文件中,写著作权复制代码时的必备良药
将目录下面所有的 .cs 文件合并到一个 code.cs 文件中,写著作权复制代码时的必备良药 @echo off echo 将该目录下所有.cs文件的内容合并到一个 code.cs 文件中! pau ...
随机推荐
- 别让Open Sans字体拖慢wordpress后台速度
最近打开wordpress后台是不是很慢?国内GG登不上了?这两者有没什么直接的联系?没错,WordPress后台是自动加载的谷歌Open Sans字体,据说gg服务器已经迁移到阿嘛丽可,需要一些小手 ...
- Linux系统启动和内核管理
Linux组成 由 kernel 和 rootfs 组成 单内核:(进程管理,内存管理,网络管理, 驱动程序,文件系统, 安全功能) /boot/vmlinuz-VERSION-release 辅助的 ...
- 使用jframe编写一个base64加密解密工具
该工具可以使用exe4j来打包成exe工具(如何打包自己百度) 先上截图功能 运行main方法后,会弹出如下窗口 输入密文 然后点击解密,在点格式化 代码分享 package tools;import ...
- C++中为何大量使用类指针
C++的精髓之一就是多态性,只有指针或者引用可以达到多态.对象不行类指针的优点: 第一实现多态. 第二,在函数调用,传指针参数.不管你的对象或结构参数多么庞大,你用指针,传过去的就是4个字节.如果用对 ...
- python 获取SLB信息 更换证书
首先安装阿里云SDK pip install aliyun-python-sdk-core pip install aliyun-python-sdk-slb 可以配合jenkins传递参数 #获取s ...
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(九)以g711-mulaw为例添加新的编码格式解析支持
一.myRtspClient音频解析架构 AudioTypeBase是处理解析各种编码的音频数据的接口类.处理MPA数据的MPEG_Audio类和处理g711-mulaw的PCMU_Audio类均从A ...
- python math random
很有用个的工具 值得好好看看,这是作者(python发明者)对于工作中使用到的大多数场景的提炼 //test.py 1 import math 2 3 print abs(-10) 4 print m ...
- datetime函数和random.seed()函数的应用
一,datetime 在python中datetime是一个库是一个模块也是一个函数,作用很多,这里面只对其做简单的最常用的讲解. 首先返回系统时间 import datetime nowTime=d ...
- webpack配置常用loader加载器
webapck中使用loader的方法有三种 使用loader之前必须运行安装 : npm install --save-dev xxx-loader (1)通过CLI : 命令行中运行 webpac ...
- Mongo数据两表关联创建视图示例
表tblCard: {"cNo":"11","oRDate":ISODate("2017-08-01T00:00:00.000+0 ...