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. ubuntu nginx 伪静态 设置

    简单的静态设置 1  vim nginx.conf // 修改nginx配置文件 server { .... root /usr/local/nginx/html; #nginx网站根目录 #下面这个 ...

  2. ubuntu svn安装测试

    本机环境 :ubuntu 12.4 LTS desktop 1 sudo apt-get install  subversion  #安装svn 2  sudo mkdir   /home/lzj/s ...

  3. 【实习记】2014-09-01从复杂到简单:一行命令区间查重+长整型在awk中的bug

        9月1号,导出sql文件后,想到了awk,但很复杂.想到了用sed前期处理+python排序比较的区间查重法.编写加调试用了约3小时. 9月2号,编写C代码的sql语句过程中,发现排序可以交m ...

  4. 解决php的$美元符号与Zen Coding冲突问题

    Zen Coding插件就不介绍了. 众所周知,安装了插件以后,输入$符号会被自动解析为相应的数字1.2.3... 作为一名PHP程序员,想要通过其定义一些自己常用的代码.却发现展开以后悲剧的发现$符 ...

  5. 《工作型PPT设计之道》培训心得

    参加包翔老师的“工作型PPT设计之道>培训,颇多心得,后来为部门新员工和同组同事做了转化培训,将心得整理成一份PPT讲义,效果颇佳.现将主要心得整理于此.因时间仓促,24条心得有拼凑之嫌,有待今 ...

  6. [转]Python中的矩阵转置

    Python中的矩阵转置 via 需求: 你需要转置一个二维数组,将行列互换. 讨论: 你需要确保该数组的行列数都是相同的.比如: arr = [[1, 2, 3], [4, 5, 6], [7, 8 ...

  7. C语言头文件书写

    说一下C语言的存储类说明符: 1.Auto       只在块内变量声明中被允许,表示变量具有本地生存期. 2.Extern    出现在顶层或块的外部变量函数与变量声明中,表示声明的对象具有静态生存 ...

  8. 介绍.NET Core

    在connect (),我们宣布.NET 核心将能完全释放,作为开放源码软件.我也答应在.NET 核心跟更多的细节.在这篇文章,我将提供.NET 核心,我们如何去释放它,它涉及到.NET 框架,如何和 ...

  9. Codeforces Round #316 div2

    一场充满血腥hack之战!!! Problem_A: 题意: n个候选人在m个城市进行投票,每个城市选出票数最多的一个候选人为城市候选人,如果票数相同,则取编号小的候选人. 再从这m个城市候选人中选出 ...

  10. BZOJ 1003: [ZJOI2006]物流运输trans DP+最短路

    Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输过程实施严格 ...