上面的代码看上去很简单,子子孙孙fork就是了,基本上符合我们的一般的猜想,逻辑上很正正确,但是要说的是:
为什么同样的代码运行的时候得到的输出会有不同?
./fork执行完成之后很正常回到了shell,但是右边却没有回到shell,这是为什么呢?
这和fork的性质【fork之后并不能确定究竟是哪个进程首先执行相关】
左边的情况是:最后一个进程4742执行完之后,父进程还是没有结束的。然后父进程结束,回到父进程的父进程也就是shell
右边的情况是:在输出[email protected]等等之前父进程就已经执行结束退出了
所以后边的子进程执行结束后不会回到shell,而是会回到他的父进程,不知道是谁了,反正不会是shell,所以会造成图中所示的现象上面说的内容不是要说的重点内容,是个人理解,不一定对,欢迎指正!
下面就来看看修改后的代码的执行情况,就和我们乍一看程序猜想或者理解上的不一致了。
同样的代码只是将打印语句的最后的‘\n‘换行符去掉了,运行效果确实差别很大:
打印出了16条语句!!!
这是为什么呢?看打印语句的内容:
其中第一条肯定是最初的进程打印的,这个不会有疑问,那么他的pid就是4772,可以看到,这个4772被打印了9次
剩下的7条分别是fork之后进程的进程pid
为什么会打印出9条?
原来这和fork的第二条性质是相关的【fork后子进程会复制父进程的资源,缓冲区是父进程的资源,所以自然会复制一份】
这样就好理解了,最初的进程有7个子孙进程,所以都复制一份一开始的缓冲区,到本身结束的时候exit会冲洗缓冲区,其中包括复制父进程的缓冲区和自己需要打印的自己的pid内容
最初的进程本身要打印两次(一开始和最后)所以就会打印2+7*2-=16条,其中4772打印2+7=9条
既然这样(子进程复制父进程的缓冲区),为什么之前打印语句中带有‘\n‘的实验就能够“正确”呢?
这是由【设备的不同缓冲属性】决定的。
我们现实运行结果的设备是标准输出设备,而【标准输出设备在正常情况下是linux中的行缓存的设备(除出错)】
‘\n‘正是换行符,所以会换行时清空缓存。
【linux中写入文件流是全缓存的,也就是换行符并不会冲洗缓冲区】我们让结果输出到文件中会是怎样的呢?
可以看到,不带‘\n‘的输出,除了没有了shell的提示符外,分析还是相同的
但是带有‘\n‘的输出到文件之后,变成了全缓冲的了,所以自然也会输出16条语句
想必经过这个实验,能对fork的特性和设备的特性有一个感性的认识了。。。。