`
dingran
  • 浏览: 375848 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

从一道面试题谈linux下fork的运行机制-转贴

阅读更多

从一道面试题谈linux下fork的运行机制

 

今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目:

      给出如下C程序,在linux下使用gcc编译:

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 1 #include "stdio.h"
 2 #include "sys/types.h"
 3 #include "unistd.h"
 4 
 5  int main()
 6 {
 7     pid_t pid1;
 8     pid_t pid2;
 9 
10     pid1 = fork();
11     pid2 = fork();
12 
13     printf("pid1:%d, pid2:%d\n", pid1, pid2);
14 }

      要求如下:

      已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。

      1、请说出执行这个程序后,将一共运行几个进程。

      2、如果其中一个进程的输出结果是“pid1:1001, pid2:1002”,写出其他进程的输出结果(不考虑进程执行顺序)。

      明显这道题的目的是考察linux下fork的执行机制。下面我们通过分析这个题目,谈谈linux下fork的运行机制。

预备知识

      这里先列出一些必要的预备知识,对linux下进程机制比较熟悉的朋友可以略过。

      1、进程可以看做程序的一次执行过程。在linux下,每个进程有唯一的PID标识进程。PID是一个从1到32768的正整数,其中1一般是特殊进程init,其它进程从2开始依次编号。当用完32768后,从2重新开始。

      2、linux中有一个叫进程表的结构用来存储当前正在运行的进程。可以使用“ps aux”命令查看所有正在运行的进程。

      3、进程在linux中呈树状结构,init为根节点,其它进程均有父进程,某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。

      4、fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

解题的关键

      有了上面的预备知识,我们再来看看解题的关键。我认为,解题的关键就是要认识到fork将程序切成两段。看下图:

从一道面试题谈linux下fork的运行机制(图一)

      上图表示一个含有fork的程序,而fork语句可以看成将程序切为A、B两个部分。然后整个程序会如下运行:

      step1、设由shell直接执行程序,生成了进程P。P执行完Part. A的所有代码。

      step2、当执行到pid = fork();时,P启动一个进程Q,Q是P的子进程,和P是同一个程序的进程。Q继承P的所有变量、环境变量、程序计数器的当前 值。

      step3、在P进程中,fork()将Q的PID返回给变量pid,并继续执行Part. B的代码。

      step4、在进程Q中,将0赋给pid,并继续执行Part. B的代码。

      这里有三个点非常关键:

      1、P执行了所有程序,而Q只执行了Part. B,即fork()后面的程序。(这是因为Q继承了P的PC-程序计数器)

      2、Q继承了fork()语句执行时当前的环境,而不是程序的初始环境。

      3、P中fork()语句启动子进程Q,并将Q的PID返回,而Q中的fork()语句不启动新进程,仅将0返回。

解题

      下面利用上文阐述的知识进

 

行解题。这里我把两个问题放在一起进行分析。

      1、从shell中执行此程序,启动了一个进程,我们设这个进程为P0,设其PID为XXX(解题过程不需知道其PID)。

      2、当执行到pid1 = fork();时,P0启动一个子进程P1,由题目知P1的PID为1001。我们暂且不管P1。

      3、P0中的fork返回1001给pid1,继续执行到pid2 = fork();,此时启动另一个新进程,设为P2,由题目知P2的PID为1002。同样暂且不管P2。

      4、P0中的第二个fork返回1002给pid2,继续执行完后续程序,结束。所以,P0的结果为“pid1:1001, pid2:1002”。

      5、再看P2,P2生成时,P0中pid1=1001,所以P2中pid1继承P0的1001,而作为子进程pid2=0。P2从第二个fork后开始执行,结束后输出“pid1:1001, pid2:0”。

      6、接着看P1,P1中第一条fork返回0给pid1,然后接着执行后面的语句。而后面接着的语句是pid2 = fork();执行到这里,P1又产生了一个新进程,设为P3。先不管P3。

      7、P1中第二条fork将P3的PID返回给pid2,由预备知识知P3的PID为1003,所以P1的pid2=1003。P1继续执行后续程序,结束,输出“pid1:0, pid2:1003”。

      8、P3作为P1的子进程,继承P1中pid1=0,并且第二条fork将0返回给pid2,所以P3最后输出“pid1:0, pid2:0”。

      9、至此,整个执行过程完毕。

      所得答案:

      1、一共执行了四个进程。(P0, P1, P2, P3)

      2、另外几个进程的输出分别为:

      pid1:1001, pid2:0

      pid1:0, pid2:1003

      pid1:0, pid2:0

      进一步可以给出一个以P0为根的进程树:

从一道面试题谈linux下fork的运行机制(2)(图二)

验证

      下面我们去linux下实际执行这个程序,来验证我们的答案。

      程序如下图:

从一道面试题谈linux下fork的运行机制(2)(图三)

      用gcc编译、执行后结果如下:

从一道面试题谈linux下fork的运行机制(2)(图四)

      由于我们不太可能刚巧碰上PID分配到1001的情况,所以具体数值可能和答案有所差别。不过将这里的2710看做基数的话,结果和我们上面的解答是一致的。

总结

      应该说这不是一道特别难或特别刁钻的题目,但是由于fork函数运行机制的复杂性,造就了当两个fork并排时,问题就变得很复杂。解这个题的关键,一是要对linux下进程的机制有一定认识,二是抓住上文提到的几个关于fork的关键点。朋友说,这个题给的时间是5分钟,应该说时间还算充裕,但是在面试的场合下,还是很考验一个人对进程、fork的掌握程度和现场推理能力。

      希望本文能帮助朋友们对fork的执行机制有一个明晰的认识

 

转自:http://www.poluoluo.com/server/201001/77829.html

 

原文乱七八糟不方便看,所以我才转载方便查看,呵呵

分享到:
评论

相关推荐

    从一道面试题谈linux下fork的运行机制

    从一道面试题深入探讨Linux下fork的运行机制 在Linux操作系统中,`fork()`系统调用是进程管理的核心功能之一,它允许一个已存在的进程创建一个新的进程,即子进程。子进程几乎完全复制父进程的状态,包括内存映像、...

    linux面试题看FORK()

    ### Linux 下 `fork()` 运行机制解析及面试题解答 #### 预备知识 在深入了解本面试题之前,我们需要掌握一些关于Linux进程管理的基础概念: 1. **进程的概念**:在Linux环境下,进程可以被视为一个正在执行的程序...

    LINUX内核经典面试题

    【Linux内核经典面试题详解】 1. Linux内核锁:Linux内核中主要有自旋锁和信号量两种锁机制。自旋锁用于保护短暂的、不会引起阻塞的临界区,而信号量则允许任务在无法获取锁时进入睡眠状态,适合处理可能长时间持有...

    linux下fork的运行机制参考.pdf

    linux下fork的运行机制 fork是Linux中一个非常重要的系统调用,它允许一个进程创建一个新的进程,该新进程是当前进程的副本。 fork的运行机制是Linux中进程创建的基础。 在Linux中,每个进程都有唯一的PID标识进程...

    eclipse-collections-forkjoin-7.1.2-API文档-中文版.zip

    赠送jar包:eclipse-collections-forkjoin-7.1.2.jar; 赠送原API文档:eclipse-collections-forkjoin-7.1.2-javadoc.jar; 赠送源代码:eclipse-collections-forkjoin-7.1.2-sources.jar; 赠送Maven依赖信息文件:...

    fork-rest-dataware-master

    fork-rest-dataware-master

    jdk-8u6-linux-arm-vfp-hflt.tar.zip

    标题“jdk-8u6-linux-arm-vfp-hflt.tar.zip”揭示了这是一款针对Linux操作系统、基于ARM架构的Java Development Kit(JDK)版本,且是64位(因为通常"u"后的数字代表更新版本,"6"可能指的是64位)。文件名中的".tar...

    Linux下Fork与Exec使用

    ### Linux下Fork与Exec使用的相关知识点 #### 一、引言 - **Fork的概念**: `fork()` 是 Unix/Linux 操作系统中最杰出的功能之一,它允许一个正在运行的进程创建一个新进程,这个新进程被称为子进程。子进程几乎是...

    linux c语言面试题

    【Linux C语言面试题】是针对C语言编程和Linux系统操作的面试准备资料,涵盖了从基础知识到高级概念的多个方面。这些题目旨在测试面试者对C语言的理解深度、编程技巧以及在Linux环境下解决问题的能力。以下是一些...

    linux_fork函数

    ### Linux中的`fork()`函数详解 #### 一、`fork()`函数基础介绍 在Linux操作系统中,`fork()`函数是一个非常重要的系统调用,用于创建一个新的进程。这个新进程被称为子进程,而调用`fork()`函数的原进程则称为父...

    linux程序员面试题

    Linux程序员面试题通常涵盖操作系统原理、C语言编程基础、Shell脚本、网络编程、文件系统、进程管理等多个方面。这份“linux程序员面试题”资源很可能包含这些关键领域的精选问题及解答,对于准备Linux相关岗位面试...

    jdk-7u75-linux-arm-vfp-hflt.tar.gz

    标题“jdk-7u75-linux-arm-vfp-hflt.tar.gz”揭示了这是一个针对Linux ARM架构的Java Development Kit (JDK) 的特定版本,版本号为7u75。"arm"表明这是专为ARM处理器设计的软件,这类处理器常见于嵌入式系统和移动...

    Linux基础使用_嵌入式-常用知识&面试题库_大厂面试真题.pdf

    Linux基础使用_嵌入式-常用知识&面试题库_大厂面试真题 本文档涵盖了Linux基础使用、嵌入式常用知识和大厂面试真题,涵盖了Linux基础知识、嵌入式系统、Linux驱动开发、makefile、shell关键命令等方面的内容。 一...

    eclipse-collections-forkjoin-7.1.2-API文档-中英对照版.zip

    赠送jar包:eclipse-collections-forkjoin-7.1.2.jar; 赠送原API文档:eclipse-collections-forkjoin-7.1.2-javadoc.jar; 赠送源代码:eclipse-collections-forkjoin-7.1.2-sources.jar; 赠送Maven依赖信息文件:...

    linux kernel常见面试题及部分答案.pdf

    Linux内核的面试题涉及多方面知识,下面将详细介绍涉及的几个主题。 一、进程管理 在Linux系统中,进程是系统进行资源分配和调度的一个独立单位。每个进程都会被分配一个唯一的进程标识符(PID)。进程管理部分的...

    mongodb-linux-x86_64-4.0.18.tgz

    tar -zxvf mongodb-linux-x86_64-4.0.18.tgz 2、重名命 mv mongodb-linux-x86_64-4.0.18 mongodb 3、进入 mongodb 目录创建目录 db 和 logs cd /usr/local/mongodb mkdir db mkdir logs 4、进入到 bin 目录下,...

    linux 进程 线程 fork 的深入思考

    本篇文章将基于一道经典的面试题目来探讨 Linux 下进程创建机制,特别是 `fork` 函数的工作原理。该题目不仅考验应试者对进程创建的理解,还涉及了对进程间关系的认识。 #### 题目描述 假设有一段 C 语言程序,在 ...

Global site tag (gtag.js) - Google Analytics