- 1、本文档共3页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
多进程Fork与Flush
多进程的上下文
——Fork与Flush
课题背景
此题出自一道某企业笔试的选择题目,题干为:
请问以下程序打印多少个‘A’?
图1-1 程序截图
题目分析
2.1一般思路
首先,我们来了解一个fork的工作流程,如图2-1。
主进程中,通过Fork建立子进程,在Fork以后,你的程序的静止状态(程序本来就是静止的)还是一个可执行映像,比如(a.out)。但在执行时已经分成两个进程:一个是Parent主进程;另一个是Child子进程。
如何区分,哪个是主进程,那个是子进程呢,通过Fork的返回值判别来实现。通常有Pid=Fork()这样的语句的写法,在你的程序中进行判定,当Pid0说明,当前位于父进程,并且Pid是Fork返回的子进程的ID;当Pid==0时,当前进程是子进程。
例如:在图1-1所示的程序中,将其编译,生成程序a.out只有一个。但是在运行到Fork的时候就分成两个进程,一个为父进程,一个位子进程。父进程和子进程同时从Fork后的第一段代码开始执行,即Printf(“A”)。如果此处加入if(Pid==0){}else if(Pid0){}else{}分支语句,在子进程中执行时if分支就会被执行,如果在父进程中执行elseif分支就会被执行,其他时候else分支执行。
图2-1 建立子进程
在正常的解法下,为了求解此题,我们会画出这样的粗略的甘特图。如图2-2所示。在图2-2中,红、绿、蓝箭头分别表示建立子进程,平行四边形分别表示Printf函数。
Main函数中有一个for循环。当i=0时,main执行fork建立一个新的进程Child1,并且随后打印‘A’;当i=1是建立一个新的进Child2,随后打印‘A’。同理Child1在i=1时创建一个新的进程child2,随后打印‘A’。
直观的从图中看出,此题打印的结果为:AAAAAA,即6个‘A’。但这并不是此题的标准解答,此题的标准解答为AAAAAAAA,即8个A。
图2-2 运行时态粗略的甘特图
可能你已经注意到了,我们将其中的一部分平行四边形用彩色标记了,问题这是出现在这里。在程序执行Fork的时候,子进程会复制父进程的数据空间、堆、栈等数据存储块为己所以,注意是复制,不是占用或者共享。不例外输出缓冲区也是要复制的。当我们使用Printf函数输出信息是,实际上输出的是输出缓冲区里面的内容。而输出缓冲区在以下一些情况才进行刷新输出,即重置缓冲区里面的数据:
有换行符“\n”时
使用fflush(stdout)的时候
缓冲区满的时候
程序退出的时候
遇到下一个printf或者scanf之类的函数时候
在图2-2中,可以清楚的看到进程Child2中在Printf(“A”)的时候,缓冲区里不只有Child2的‘A’,还有从Main缓冲区中复制过来的‘A’,因为此时没有从满足上述四个刷洗缓冲区的条件,所以打印的是‘AA’。同理Child3中也打印的是‘AA’。综上所述,其最终结果如图2-3所示。
图2-3 最终本题的结果
Main
Child1
Child2
Child3
A
A
A
A
A
A
i=0
i=1
i=1
Main
Fork
Child
Parent
Pid0
Pid==0
i=1
i=1
i=0
A
AA
AA
A
A
A
Child3
Child2
Child1
Main
文档评论(0)