fork遗留习题详解


我们先来解决一下第二题,它和我们上篇的第一题区别是什么呢?
 我们会发现原来的每次输出后面都会有一个‘\n’,这一题的输出是都没有'\n'。我们要解决这道题首先要清楚‘\n’的作用是什么。
提到这个,我们就连着和'\n'差不多功能的知识点一起复习一下。设计操作系统的人非常聪明,它并不是产生一个字符就调用I/O输出,因为如果这样的话,那cpu大量的时间都在完成I/O中断处理了,这样的效率就非常低了。聪明的操作系统设计员当然不会让这样如此低效的事情发生,他们的解决方法是在内存中划出一小块区域作为输入输出的缓冲区,每当有字符要输出时,并不立即输出,而是等待一个刷新缓冲区的信号才会一起输出,刷新缓冲区有以下几种方式:
 1、遇到‘\n’,立即刷新缓冲区。
 2、程序调用fflush函数也能刷新缓冲区。
 3、程序以exit结束,缓冲区会刷新。函数以_exit结束则会清空缓冲区。
 4、缓冲区满,也会将数据刷新出来。
  注意刷新的意思是将缓冲区里的数据像水流一样倒出来,全部输出,而清空是不会输出的。
 好了明白了这些,我们再次回到这个题目。输出没有‘\n’意味着缓冲区不会刷新。在同一个进程中,如果要求输出两次,因为第一次输出的内容没有刷新,那第一次的内容还在,第二次输出除了有自己本身的内容输出,还会在输出前将第一次的内容再输出一遍,这都是因为缓冲区没有刷新,而printf只是将缓冲区里的内容格式化输出,没有刷新的作用。那这个题目会输出什么呢?我们看看下面的分析图。



对于第一个父进程来说, i=0时,进入第一次循环,完成第一次fork,产生一个子进程,在 父进程里输出为 A,在 子进程里输出为 B。现在两个进程都进入 i=1了,也就是第二次循环了。因为 原来的父进程再次调用fork,那又会产生 一个A放在缓冲区,注意,此时打印, 由于第一次没有刷新,则会打印 两个A,而现在新产生的子进程由于把内容都复制过来了,包括缓冲区(有1个A没刷新)过来时, i=1了,所以它就输出AB。对于 原来的子进程,它 为1时,进入循环 调用fork,那它相对来说就是父进程了,它 产生一个A到缓冲区中,所以 加上第一次产生B,printf会打印 BA。而 它产生的子进程把它的内容复制过来了(1个B)加上它自己本身要输出的B,所以输出BB,所以这次的输出是 4个A,4个B,顺序也是不确定的,原因我上一篇提过了,这里就不作多余解释了。
 好了,有了两道题练手,我们看第三个题目是不是渐入佳境,觉得这类题目也不是特别难了呢!我们看看第三个题目,它和第一题的区别是if语句中用或连接了两个fork函数,这会产生什么情况呢,我们也先看图分析。



        在 i为0的时候父进程 进入了第一次循环,调用 fork产生了一个子进程,因为 ||有短路的作用,所以在父进程中因为调用fork产生了非0,||后面的指令也 就不会做了,但是在子进程中因为fork返回为0,所以还会执行||后面的语句,那在2(我就用数字标识进程了,因为太多,怕把大家绕混)中,会再次调用fork又产生一个子进程3,然后,2会输出A因为它现在作为父进程,两次中只要有一次做了父进程,也就是有一次非0,则进入if输出A。然后在3中的时候,因为程序计数器已经指向了下一条指令,那3就不能像2一样还有逆转了,到目前为止已经有3个进程了,并且它们的i现在都为0,输出完成后都要进入i为1时的循环了。我们再看i为1时,1进程再次,fork返回非零,||后面的指令被短路,所以输出A,产生了4进程,因为4进程此时为子进程fork返回为0,所以又会做||后的fork再完成一次调用,而此时,它产生了进程7,所以这一次它是父进程了,两次返回又一次非0,所以4进程输出A,而产生的7进程输出B,因为此时1,4和7的i的值都为1了,所以都结束循环了。后面的5和8,6和9都是同样的道理,所以就不多做解释了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值