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. ASP.Net大文件上传组件详解

    首先右键单击网站根目录,在弹出的快捷菜单中,选择"添加引用"菜单项,弹出"添加引用",切换到"浏览"找到组件的Dll文件"Best ...

  2. PHP异常处理

    一.异常处理——可以有效地控制多条出现错误或异常的代码 基本语法如下: try{ //可能出现异常的代码 } catch(Exception $e){ //对异常处理 //1.自己处理 //2.不作处 ...

  3. struts2整合jfreechart

    需要的包: struts2-jfreechart-plugin-2.2.1.1.jar jfreechart-1.0.13.jar jcommon-1.0.17.jar 前台jsp页面中可以使用ifr ...

  4. web2py相关-------------------------------(一)初遇

    在第一次换工作的时候,希望转行 做编程,就面试了很多家,很多人问我 懂不懂html 书写,我非常诚实的告诉他们不会. 当然那时我很天真的认为,只要自己愿意学习这些都不是问题,事实证明人的学习能力是很快 ...

  5. STM32库函数开发使用总结

    一.外设常具备的几类寄存器 控制寄存器xxx_CR (Control/Configuration Register): 用来配置.控制响应外设的工作方式,如GPIOx_CRL.AFIO_EXTICR1 ...

  6. delphi xe5 android 开发数据访问手机端(一)

    上几片文章我们把供手机端调用的web服务完成,接下来实现手机端调用webservices获取数据 1.新建firemonkey mobile application 2.选择blank applica ...

  7. css3媒体查询判断移动设备横竖屏

    /* 设备竖屏时调用该段css代码 */ @media all and (orientation : portrait){ body{   background-color:blue;  } } /* ...

  8. Android手机上监听短信的两种方式

    Android手机上监听短信有两种方式: 1. 接受系统的短信广播,操作短信内容. 优点:操作方便,适合简单的短信应用. 缺点:来信会在状态栏显示通知信息. AndroidManifest.xml: ...

  9. csu 10月 月赛 B 题 Scoop water

    一个卡特兰数的应用: 卡特兰数主要有以下几个用途: 1.不同的出栈入栈数: 2.n个点组成的不同的二叉树的数目: 3.凸多边形的三角剖分划分: 4.括号化问题: 通项公式是:h(n) = C(2n-2 ...

  10. 【2011 Greater New York Regional 】Problem H: Maximum in the Cycle of 1

    也是一个数学题: 主要用到的是排列组合的知识,推推公式就行了,挺简单的: 唯一要注意的是A(0,0)=1: 在这个上面WA了几次,= = 代码: #include<stdio.h> #de ...