fork在面试中经常被问到,在这里复习一下。

  frok创建子进程,父子进程共享.text段,子进程获得父进程数据段、堆和栈的副本,由于在fork之后经常跟随者exec,所以很多实现并不执行父进程数据段、堆和栈的完全复制,而是使用写时复制(Copy-On-Write,COW)技术。这些区域由父子进程共享,并被内核设为只读,如果父子进程试图修改这些区域,则内核只为修改区域的那块内存制作一个副本。

接下来的程序演示一下fork函数的功能

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h> void err_sys(const char *s)
{
printf("error:%s",s);
exit(EXIT_FAILURE);
} int glob = ;
char buf[] = "a write to stdout\n"; int main()
{
int var;
pid_t pid; var = ;
if(write(STDOUT_FILENO,buf,sizeof(buf)-) != sizeof(buf)-)
err_sys("write error");
printf("before fork\n");
if((pid = fork())<)
err_sys("fork error");
else if(pid == )
{
glob++;
var++;
}
else
sleep();
printf("pid = %d,glob = %d,var = %d\n",getpid(),glob,var);
exit();
}

编译得到fork_sample,运行结果如下:

当直接执行fork_sample时,结果不出乎意料。在fork前先打印"before fork\n",fork之后父子进程分别打印。

但是当程序输出重定向到temp文件时(即./fork_sample > temp的作用),读取temp文件(即cat temp),我们发现"before fork\n"被输出了两遍,这是为什么呢?

这得从标准I/O库的缓冲说起。

标准I/O库提供了三种类型的缓冲:

(1) 全缓冲:填满标准I/O缓冲区才实际进行I/O操作。

(2)行缓冲:在输入和输出中遇到换行符时,标准I/O库执行I/O操作,当流涉及终端时,通常使用行缓冲。

(3)不带缓冲:标准出错流stderr通常是不带缓冲的。

上面说的缓冲指的是应用层的缓冲,在进行实际的I/O操作时,相关的系统调用(read和write)其实在内核也有缓冲区的。

当直接执行./fork_sample时,由于标准输出时行缓冲的,所以遇到换行符'\n'后缓冲区被冲洗。

当将程序输出重定向到别的文件时,是标准输出是全缓冲的,fork之前printf的数据仍在缓冲区中,在fork时该缓冲区也被复制到子进程中,因此我们就会看到"before fork\n"输出了两次。

fork和缓冲区的更多相关文章

  1. printf 缓冲区问题

    突然发现printf的问题,看了这个很有意思,学习一下 转自:http://blog.csdn.net/shanshanpt/article/details/7385649 昨天在做Linux实验的时 ...

  2. linux中的fork函数的基本用法

    代码: #include <iostream> #include <string> #include <cstdio> #include <unistd.h& ...

  3. 笔试中常用c++接口

    1.stack:https://www.cnblogs.com/hdk1993/p/5809161.html 使用该容器时需要包含#include<stack>头文件: 定义stack对象 ...

  4. 关于标准I/O缓冲区和fork函数

    标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数.标准I/O提供三个类型的缓冲:全缓冲.行缓冲和不带缓冲.标准输入(stdin)和标准输出(stdout)是行缓冲,标准出错(s ...

  5. 文件缓冲区在fork后复制

    场景:父进程trace进程A,当A进程fork子进程B时,让父进程也fork子进程去trace子进程B,用于trace的进程将被trace的进程发生的系统调用号通过fprintf存入各自文件中 问题: ...

  6. fork调用实验-缓冲区相关

    先看下面一段代码: #include <unistd.h> #include <stdio.h> ; char buf[] = "a write to stdout\ ...

  7. Linux0.11内核--内存管理之2.配合fork

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5598451.html ] 在上一篇的fork函数中,首先一上来就调用get_free_page ...

  8. fork()创建子进程

    fork()系统调用是Unix下以自身进程创建子进程的系统调用,一次调用,两次返回,如果返回是0,则是子进程,如果返回值>0,则是父进程(返回值是子进程的pid) 在fork()的调用处,整个父 ...

  9. fork与vfork

    先看一个fork的例子: ; int main(void) { int var, pid; ; ) { printf("vfork error"); exit(-); } ) { ...

随机推荐

  1. thinkphp 整合 ucenter

    http://xcodebox.com/2013/06/8855.html 参考 1   ucenter源码目录下 /advanced/examples/api目录 copy到thinkphp项目根目 ...

  2. 网站开发常用jQuery插件总结(13)定位插件scrollto

    一.scrollto插件功能 scrollto用于定位页面中元素的位置,并使滚动条滚动到当前元素. 二.scrollto官方地址 https://github.com/flesler/jquery.s ...

  3. GDI画验证码

    Random r = new Random(); string str = ""; for (int i = 0; i < 5; i++) { int a= r.Next(0 ...

  4. React组件三

    <script> <!-- getDefalutPros 设置组件的默认值--> <!--var Mytitle=React.createClass({ getDefau ...

  5. 青瓷qici - H5小游戏 抽奖机 4 运行脚本编写

    hello,小伙伴们,我们来继续编写相关的程序. 前几章我们已经基本把界面等问题搞定了,现在我们就来写脚本让整个流程统一起来. 看看我们现在有了什么?一个界面还有他的层次结构 青瓷界面绑定UI.js创 ...

  6. gulp和webpack初探

    gulp 真正“流程”化工具 我记得实习刚刚进公司看到grunt,还是有点蒙,之前一直是本地开发,游览器F5,没想到前端也需要“编译工具”.所以grunt一直给我的感觉是“编译工具”,你写的很多代码还 ...

  7. windows下python 编码问题

    windows下py文件编码: 当print 时遇到unicode 会根据系统编码转换, 而raw_input 中的输出遇到unicode编码是不会的转码的,会报错UnicodeEncodeError ...

  8. Mac 配置java版本 ---- MySql数据库权限设置 --- openfire

    java -version 显示java 版本 sudo su - root 切换身份 cd /usr/local/openfire 进入openfire目录 cd bin/ 进入 bin vim o ...

  9. 关于Action中ValidateXXX方法校验一次失败后\导致以后一直返回input视图的情况

    问题:     使用struts2的validateXXX()进行验证,出错后自动返回之前的画面,但是Form中的数据全部丢失了,如何才能保存出错前的Form是要解决的问题. 调查:     调查后发 ...

  10. nojs iis asp.net mvc

    http://blogs.msdn.com/b/scott_hanselman/archive/2011/11/29/window-iis-node-js.aspx http://www.hansel ...