一、文章来由

还是按照惯例来说一下文章为什么来的。晚上好基友在网上刷面试题,看到一个有趣的题目,于是開始了研究,就有了这篇文章。

二、进入正题

题目例如以下:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int main(void)
{
int i;
for(i=0; i<2; i++){
fork();
printf("-");
} return 0;
}

绘图理解一下:

假设对fork()的机制比較熟悉的话,上图应该不难理解,数一下超人标志的个数就知道应该是6个

可是,实际上这个程序会非常tricky地输出8个“-”。

下图把”-“改成”s”了

以下開始有借鉴大牛的博客

要讲清这个题。我们首先须要知道fork()系统调用的特性

  1. fork()系统调用是Unix下以自身进程创建子进程的系统调用。一次调用,两次返回。假设返回是0,则是子进程。假设返回值>0,则是父进程(返回值是子进程的pid)。这是众为周知的。

    这个能够有方法巧记一下,就是子进程从fork開始处開始运行。可是此时没有子进程。所以返回值是0;

  2. 另一个非常重要的东西是,在fork()的调用处。整个父进程空间会原模原样地拷贝到子进程中,包含指令,变量值。程序调用栈,环境变量。缓冲区,等等。

所以,上面的那个程序为什么会输入8个“-”,这是由于printf(“-“);语句有buffer。所以,对于上述程序。printf(“-“);把“-”放到了缓存中。并没有真正的输出(參看《C语言的迷题》中的第一题),在fork的时候,缓存被拷贝到了子进程空间。所以,就多了两个,就成了8个,而不是6个。

另外。多说一下。我们知道。Unix下的设备有“块设备”和“字符设备”的概念。所谓块设备。就是以一块一块的数据存取的设备。字符设备是一次存取一个字符的设备。磁盘、内存都是块设备,字符设备如键盘和串口。块设备一般都有缓存。而字符设备一般都没有缓存。

对于上面的问题,我们假设改动一下上面的printf的那条语句为:

printf("-\n");

或是

printf("-");
fflush(stdout);

就没有问题了(就是6个“-”了)。由于程序遇到“\n”,或是EOF,或是缓中区满。或是文件描写叙述符关闭,或是主动flush。或是程序退出,就会把数据刷出缓冲区。

须要注意的是。标准输出是行缓冲。所以遇到“\n”的时候会刷出缓冲区。但对于磁盘这个块设备来说,“\n”并不会引起缓冲区刷出的动作,那是全缓冲,你能够使用setvbuf来设置缓冲区大小。或是用fflush刷缓存。

我预计有些朋友可能对于fork()还不是非常了解,那么我们把上面的程序改成以下这样:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
int i;
for(i=0; i<2; i++){
fork();
//注意:以下的printf有“\n”
printf("ppid=%d, pid=%d, i=%d \n", getppid(), getpid(), i);
}
sleep(10); //让进程停留十秒,这样我们能够用pstree查看一下进程树
return 0;
}

于是。上面这段程序会输出以下的结果,(注:编译出的可运行的程序名为fork)

ppid=8858, pid=8518, i=0
ppid=8858, pid=8518, i=1
ppid=8518, pid=8519, i=0
ppid=8518, pid=8519, i=1
ppid=8518, pid=8520, i=1
ppid=8519, pid=8521, i=1 $ pstree -p | grep fork
|-bash(8858)-+-fork(8518)-+-fork(8519)---fork(8521)
| | `-fork(8520)

面对这种图你可能还是看不懂,没事。我好事做究竟,画个图给你看看:

注意:上图中的我用了几个色彩,同样颜色的是同一个进程。

于是,我们的pstree的图示就能够成为以下这个样子:(下图中的颜色与上图相应)

这样,对于printf(“-“);这个语句,我们就能够非常清楚的知道,哪个子进程复制了父进程标准输出缓中区里的的内容,而导致了多次输出了。(例如以下图所看到的,就是我阴影并双边框了那两个子进程)

—END—


从fork面试题開始的思考的更多相关文章

  1. C语言必会面试题(3、耶稣有13个门徒,当中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个開始报号:1,2,3,1,2,3...。凡是报到“3”就退出圈子,...)

    3.耶稣有13个门徒.当中有一个就是出卖耶稣的叛徒,请用排除法找出这位叛徒:13人围坐一圈,从第一个開始报号:1.2,3.1,2,3.... 凡是报到"3"就退出圈子.最后留在圈子 ...

  2. ExtJs自学教程(1):一切从API開始

    题 记 该系列文章不側重全方位的去介绍ExtJs的使用,仅仅是側重于解决ExtJs问题的思考方法.写的人不用长篇大论,学的人则可以自立更生.l  学习的人仅仅要有一些CSS的javascript的基础 ...

  3. WebGL自学教程——WebGL演示样例:開始

    最终開始WebGL的演示样例了,...... 開始 使用WebGL的步骤,非常easy: 1. 获得WebGL的渲染环境(也叫渲染上下文). 2. 发挥你的想象力,利用<WebGL參考手冊> ...

  4. 关东升的《从零開始学Swift》即将出版

    大家好: 苹果2015WWDC大会公布了Swift2.0,它较之前的版本号Swift1.x有非常大的变化.所以我即将出版<从零開始学Swift><从零開始学Swift>将在&l ...

  5. 从0開始学习 GitHub 系列之「07.GitHub 常见的几种操作」

    之前写了一个 GitHub 系列,反响非常不错,突然发现居然还落下点东西没写,前段时间 GitHub 也改版了,借此机会补充下. 我们都说开源社区最大的魅力是人人多能够參与进去,发挥众人的力量,让一个 ...

  6. 兼容,原来在这里就已经開始--------Day34

    看了两天,算是将w3cschool的javascript部分浏览了一遍.在脑海中大约有了一点概念,也才真切体会到:一入江湖深似海.欲穷此路难上难啊,至少如今看起来是遥遥无期.太多不懂, 太多茫然,只是 ...

  7. [WebGL入门]二,開始WebGL之前,先了解一下canvas

    年2月)HTML5依旧处于草案阶段. HTML5支持网页端的多媒体功能和画布功能,追加了非常多全新的更合理的Tag标签.各个浏览器也都在逐渐的完好这些新的特性. Canvas对象表示一个 HTML画布 ...

  8. 開始Unity3D的学习之旅

    前言:这个系列的文章纯属对自己学习的整理,非高手之作.但确实的记载了我作为一个没接触过3D游戏编程的大学生的心路历程.争取每周整理一次吧.之所以会開始学Unity3D,最基本的原因是由于在快放暑假的时 ...

  9. csdn博客又開始更新了

    csdn博客经过两年多的沉寂又開始更新了,这两年偶尔在http://www.cnblogs.com/JerryWang1991/ 写一些博文,写的也比較少,如今工作一年多了,又開始回到csdn上更新. ...

随机推荐

  1. Linux下的进程环境

    僵尸进程.孤儿进程.守护进程.进程组.会话.前台进程组.后台进程组 1,僵尸进程 子进程结束,父进程没有明确的答复操作系统内核:已收到子进程结束的消息.此时操作系统内核会一直保存该子进程的部分PCB信 ...

  2. org.apache.hadoop.ipc.Client: Retrying connect to server

    这个问题导致jps查看结点进程时发现找不到NodeManager或一段时间后消失,网上查找了很多博客,因hadoop版本不一样且出错的原因也可能不同,所以找了老半天. 步骤:jps --> 看l ...

  3. eclipse project文件夹下 删除不掉文件夹或者文件的解决的方法

    对于新手来说,有时操作失误就会导致eclipse文件夹中的某些子文件夹或者文件无法删除. 这种原因是,在project文件夹中(不是eclipse上显示的.是真实的物理磁盘上的)这个文件夹或者文件已经 ...

  4. 怎样制作C#安装程序

    近期须要制作一个C#安装.在网上找了一些资料发现都不是非常完整,最后自己综合了一些资料,而且通过亲自检測,最后成功完毕C#打包成安装程序(打包成最简单的一种安装程序.假设须要更高的功能请自己在开发). ...

  5. [Angular] Send Data via HTTP using Angular HttpParams

    Obviously in a real world application we do not only fetch data from the backend, but we also send d ...

  6. Linux下永久改动MAC地址和ifconfig命令总结

    1. 固定一个MAC地址,特别是在使用多个虚拟机的时候 linux环境下: 用root身份登录,在/etc/rc.d/rc.local里加上这三句 ifconfig eth0 down ifconfi ...

  7. POJ-3264-Balanced Lineup-单点更新

    题目链接:id=3264">http://poj.org/problem? id=3264 这是一个单点更新的模板题,就不详解了,HDU敌兵布阵那题我有详解:链接:http://blo ...

  8. CCControlExtension/CCControlPotentiometer

    #ifndef __CCCONTROLPOTENTIOMETER_H__ #define __CCCONTROLPOTENTIOMETER_H__ #include "CCControl.h ...

  9. Educational Codeforces Round 6 B. Grandfather Dovlet’s calculator 暴力

    B. Grandfather Dovlet’s calculator   Once Max found an electronic calculator from his grandfather Do ...

  10. m_Orchestrate learning system---十七、页面美观的关键是什么

    m_Orchestrate learning system---十七.页面美观的关键是什么 一.总结 一句话总结:图片用好看的 1.项目板块化? 就是一个个模块,能复用的话很快的 页面由这一个个模块拼 ...