fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看

fork()的原理是什么样的?学习中遇到了问题,标题不足以解释疑问请进来看看
那什么,似乎有3个问题,不过都是fork()的原理问题,我把要问的问题用加粗什么的表示一下……希望有人回答呜呜(……
板块如果有选错请包涵!

为了理解先写了一个类似的程序。
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
在这个程序中运行了两个进程。主程序pid为3389(由getpid()得知),先执行print “hello world!”,之后fork()创建进程,其pid=3390,接下来。打印pid,子程序p1=3390,p2=3389。
之后进入子进程3390,print “hello world!”,不再fork()新进程。最后打印pid。由于3390是子进程,fork对自身返回0。此时p1=0,p2=3390。
疑问是为什么子进程做了和父进程一样的操作,虽然没有再fork()产生子程序可以理解。通过百度已解决:fork()会拷贝自身代码段。
http://os.chinaunix.net/a2012/0203/1306/000001306508.shtml
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
乍看过去,似乎执行了四次进程,但是代码里只出现了两次fork(),应当只运行三次。为了方便理解,又对程序进行了修改,在输出后加上了输出当前进程的操作。
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
加上getpid()之后,代码就更加好理解了:(按照上面的结果来说明)
1.进入主程序,pid=3575,fork()出3576和3577两个进程,打印pid1=3576,pid2=3577;
2.进入pid=3576,由于自身对应3575的pid1调出的程序,便不执行pid1=fork(),但是有执行pid2=fork(),创建3578进程,打印pid1=0,pid2=3578; (不能理解为什么pid2有执行!)
3.进入pid=3577,由于父进程是3575,其pid1已经调用出3576,而自身是父进程通过pid2调用出的,因此pid1和pid2的fork()操作都没有调用,打印pid1=3576,pid2=0;
4.进入pid=3578,自己是祖先进程的pid1 调用出的3576,的pid2调用出的进程,因此啥也没fork(),打印pid1=0,pid2=0。

通过另外一篇资料http://blog.csdn.net/lingdxuyan/article/details/4993883 
明白了fork()在拷贝了代码之后,两个进程更像兄弟进程,共享代码空间,但是子进程是拷贝了父进程的数据空间之后独立保存的。子进程拥有父进程当前运行到的位置,也就是说,3576从pid1=fork();开始独立运行自己的进程,于是fork()出了3578,而3577和3578什么也做不了。
并且,子程序的数据似乎不是在fork()时就完全拷贝的,而是父进程在进入子进程的时候才拷贝的数据?这样似乎可以解释为什么3577的pid1是3576。
但是!这解释又没办法解释我自己写的程序为什么都会打出“hello world!”的问题了……(救命
(另外)
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
 fork()的原理是什么样的?学习中遇到了有关问题,标题不足以解释疑问请进来看看
上面两次执行结果和第一次执行结果的区别在于程序似乎被中断过,在运行程序期间先切换回了terminal进程,打印出了命令行之后切换回./a.out进程继续打印结果。
 
------解决方案--------------------
>这解释又没办法解释我自己写的程序为什么都会打出“hello world!”的问题了
stdio是有缓存的。fork的时候因为是整个地址空间都给拷过去了,所以在io缓存里还没输出的东西也会给拷过去,所以你会看到即使hello world在fork之前但还是会输出2次的现象。你fork前加个flush(stdout)强制刷新缓存就不会有这现象了。