父进程与子进程之间的 困惑!

jqx_ah 2008-09-09 01:22:41
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int main(void)
{
pid_t pid2;
pid_t pid=fork();
if(pid==0)
{
int j ;
for(j=0;j<5;j++)
{
printf("child: %d\n",j);
sleep(1);
}
}
else if (pid>0)
{
int i;
for(i=0;i<5;i++)
{
printf("parent: %d\n",i);
sleep(1);
}
}
else
{
fprintf(stderr,"can't fork ,error %d\n",errno);
exit(1);
}
pid2=fork();
if(pid2==0){printf(" pid2 \n");}
printf("This is the end !\n");
return 0;
}

-------------------------------------------------------------------
./a.out
结果是:jqx2008@jqx55ah:~$ ./a.out
child: 0
parent: 0
child: 1
parent: 1
child: 2
parent: 2
child: 3
parent: 3
child: 4
parent: 4
pid2
This is the end !
pid2
This is the end !
This is the end !
jqx2008@jqx55ah:~$ This is the end !


问题是:一共会产生几个子进程?
输出结果 最后,面那5行怎么解释啊 ?
-------------------------------------------------------
同样这个题目:
./a.out > ty.txt
输出结果却是:

child: 0
child: 1
child: 2
child: 3
child: 4
pid2
This is the end !
parent: 0
parent: 1
parent: 2
parent: 3
parent: 4
pid2
This is the end !
parent: 0
parent: 1
parent: 2
parent: 3
parent: 4
This is the end !
child: 0
child: 1
child: 2
child: 3
child: 4
This is the end !

为什么将结果写进文件 就是这样一个形式了?

大家抽个时间 解释撒!
谢谢哈!
...全文
478 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
yangyibin 2009-05-13
  • 打赏
  • 举报
回复
我用2楼程序运行发现最后6行并不固定,以下几个情况都随机出现:
情况1
6917--6914: pid2
6917--6914: This is the end !
6918--6913: pid2
6918--6913: This is the end !
6914--6913: This is the end !
6913--4174: This is the end !
情况2
6921--6920: pid2
6921--6920: This is the end !
6922--6919: pid2
6922--6919: This is the end !
6919--4174: This is the end !
yyb@yyb-desktop:~/myprog/exec$ 6920--1: This is the end !
情况3
6931--6930: pid2
6931--6930: This is the end !
6930--6929: This is the end !
6932--6929: pid2
6932--6929: This is the end !
6929--4174: This is the end !
而其中情况2出现概率大。
zzjjlzh 2008-09-13
  • 打赏
  • 举报
回复
真是长知识啊,不错,学习了
jqx_ah 2008-09-09
  • 打赏
  • 举报
回复
谢谢哈!了解了!
jqx_ah 2008-09-09
  • 打赏
  • 举报
回复
9#的结果 很好理解ha !
可我用2#的代码运行
结果却是:
14582--14581: child: 0
14581--13075: parent: 0
14582--14581: child: 1
14581--13075: parent: 1
14582--14581: child: 2
14581--13075: parent: 2
14582--14581: child: 3
14581--13075: parent: 3
14582--14581: child: 4
14581--13075: parent: 4
14584--14582: pid2
14584--14582: This is the end !
14585--14581: pid2
14585--14581: This is the end !
14581--13075: This is the end !
jqx2008@jqx55ah:~$ 14582--1: This is the end !

难道是我的终端问题?
略略明白了一些
谢谢大家
brookmill 2008-09-09
  • 打赏
  • 举报
回复
关于6楼和7楼的问题:
fork之后,父进程和子进程执行的先后次序,本身是不确定的。如果不用wait之类的函数来人为控制,有可能父进程先执行,也可能子进程先执行。
7楼的shell提示符"jqx2008@jqx55ah:~$",是在父进程14262结束的时候打印出来的,而这时子进程14263还没结束,所以出现了6楼所说的现象;而且由于14263的父进程在它结束之前就先结束了,所以14263被系统的init进程(1号进程)给“收养”了
brookmill 2008-09-09
  • 打赏
  • 举报
回复
9楼的结果就很清楚了,确实和缓冲区有关。
貌似可以这样解释:
当运行a.out的时候,printf的结果会很快从缓冲区里输出;
而运行a.out > ty.txt的时候,printf的结果会在缓冲区里存放很长时间,可能是操作系统不太舍得频繁向硬盘里写数据。
brookmill 2008-09-09
  • 打赏
  • 举报
回复
为了验证8楼的想法,把2楼的printf后面都加上fflush:
int main(void)
{
pid_t pid2;
pid_t pid=fork();
if(pid==0)
{
int j ;
for(j=0;j <5;j++)
{
printf("%d--%d: child: %d\n",getpid(), getppid(),j);
fflush(stdout); ///////////////////////
sleep(1);
}
}
else if (pid>0)
{
int i;
for(i=0;i <5;i++)
{
printf("%d--%d: parent: %d\n",getpid(),getppid(),i);
fflush(stdout); ///////////////////////
sleep(1);
}
}
else
{
fprintf(stderr,"can't fork ,error %d\n",errno);
exit(1);
}
pid2=fork();
if(pid2==0){printf("%d--%d: pid2 \n", getpid(), getppid());}
printf("%d--%d: This is the end !\n",getpid(), getppid());
return 0;
}

这次./a.out > ty.txt 的结果:
25595--25594: child: 0
25594--25384: parent: 0
25594--25384: parent: 1
25595--25594: child: 1
25594--25384: parent: 2
25595--25594: child: 2
25594--25384: parent: 3
25595--25594: child: 3
25594--25384: parent: 4
25595--25594: child: 4
25596--25594: pid2
25596--25594: This is the end !
25594--25384: This is the end !
25597--25595: pid2
25597--25595: This is the end !
25595--1: This is the end !
brookmill 2008-09-09
  • 打赏
  • 举报
回复
从5楼的结果来看,父进程25536貌似执行了2次,但我们都知道那是不可能的。
所以恐怕只能用缓冲区来解释了:父进程25536先打印了5行parent%d在缓冲区里,然后被子进程25537复制过去,然后在25536和25537里各输出了一次?
jqx_ah 2008-09-09
  • 打赏
  • 举报
回复
我的gcc编译器运行2楼的结果是:

14263--14262: child: 0
14262--13075: parent: 0
14263--14262: child: 1
14262--13075: parent: 1
14263--14262: child: 2
14262--13075: parent: 2
14263--14262: child: 3
14262--13075: parent: 3
14263--14262: child: 4
14262--13075: parent: 4
14266--14262: pid2
14266--14262: This is the end !
14265--14263: pid2
14265--14263: This is the end !
14262--13075: This is the end !
jqx2008@jqx55ah:~$ 14263--1: This is the end !


我想最后6行应该为:
pid2
This is the end !
This is the end !
pid2
This is the end !
This is the end !
jqx2008@jqx55ah:~$


还请指教!
jqx_ah 2008-09-09
  • 打赏
  • 举报
回复
另外 最后一行的输出也挺奇怪的!
jqx2008@jqx55ah:~$ This is the end !

This is the end !在后面去了!

而且终端只有再按一下回车!
才能正常显示下面一行:
jqx2008@jqx55ah:~$
brookmill 2008-09-09
  • 打赏
  • 举报
回复
用2楼的代码,运行./a.out > ty.txt
结果:
25536--25384: parent: 0
25536--25384: parent: 1
25536--25384: parent: 2
25536--25384: parent: 3
25536--25384: parent: 4
25538--25536: pid2
25538--25536: This is the end !
25536--25384: parent: 0
25536--25384: parent: 1
25536--25384: parent: 2
25536--25384: parent: 3
25536--25384: parent: 4
25536--25384: This is the end !
25537--25536: child: 0
25537--25536: child: 1
25537--25536: child: 2
25537--25536: child: 3
25537--25536: child: 4
25539--25537: pid2
25539--25537: This is the end !
25537--25536: child: 0
25537--25536: child: 1
25537--25536: child: 2
25537--25536: child: 3
25537--25536: child: 4
25537--1: This is the end !

25384:shell
25536:父进程
25537:第一次fork产生的子进程
25538:父进程产生的子进程pid2
25539:25537产生的子进程pid2
至于为什么是这个结果,我暂时还没想出来。
jqx_ah 2008-09-09
  • 打赏
  • 举报
回复
那 那个文件输出又是什么问题?!
brookmill 2008-09-09
  • 打赏
  • 举报
回复
2楼的代码执行结果:
$ ./a.out
25520--25519: child: 0
25519--25384: parent: 0
25519--25384: parent: 1
25520--25519: child: 1
25519--25384: parent: 2
25520--25519: child: 2
25519--25384: parent: 3
25520--25519: child: 3
25519--25384: parent: 4
25520--25519: child: 4
25521--25519: pid2
25521--25519: This is the end !
25519--25384: This is the end !
$ 25522--25520: pid2
25522--25520: This is the end !
25520--1: This is the end !

25384:shell
25519:父进程
25520:第一次fork产生的子进程
25521:父进程产生的子进程pid2
25522:25520产生的子进程pid2
brookmill 2008-09-09
  • 打赏
  • 举报
回复
1楼说错了。
第一个fork执行了1次,
pid2=fork(); 这个由父进程和第一个fork产生的第一个子进程各执行了一次
所以一共产生了3个子进程。
"This is the end ! "和缓冲区没关系,它被父进程和3个子进程各执行了一次。
把所有的printf都加上pid和ppid应该就能看清楚了:
int main(void)
{
pid_t pid2;
pid_t pid=fork();
if(pid==0)
{
int j ;
for(j=0;j <5;j++)
{
printf("%d--%d: child: %d\n",getpid(), getppid(),j);
sleep(1);
}
}
else if (pid>0)
{
int i;
for(i=0;i <5;i++)
{
printf("%d--%d: parent: %d\n",getpid(),getppid(),i);
sleep(1);
}
}
else
{
fprintf(stderr,"can't fork ,error %d\n",errno);
exit(1);
}
pid2=fork();
if(pid2==0){printf("%d--%d: pid2 \n", getpid(), getppid());}
printf("%d--%d: This is the end !\n",getpid(), getppid());
return 0;
}

brookmill 2008-09-09
  • 打赏
  • 举报
回复
调用了2次fork,所以产生2个子进程
至于输出的问题,我也不是很明白,不过有个印象,在fork的时候,子进程复制了父进程的资源,其中包括输出缓冲区,所以"This is the end ! "可能是子进程复制过去之后由子进程输出的。
Re: 《Linux 进程管理命令》   ---------------------------------------内容提要: 01/15)命令 ps         :查看进程(快照)02/15)命令 pstree   :显示进程状态树03/15)命令 pgrep   :查找匹配条件的进程04/15)命令 kill        :终止进程号(1277)05/15)命令 killall    :通过进程名(nginx)终止进程/进程)06/15)命令 pkill      :通过进程名终止进程(通杀)/终止客户端(pst/tty)07/15)命令 top       :实时显示系统中各个进程的资源占用状况(录像)08/15)命令 nice      :调整程序运行时的优先级09/15)命令 renice   :调整运行中的进程的优先级10/15)命令 nohup  :用户退出系统,进程继续工作11/15)命令 strace   :跟踪进程的系统调用12/15)命令 ltrace    :跟踪进程调用库函数13/15)命令 runlevel:输出当前运行级别14/15)命令 init        :初始化 Linux 进程15/15)命令 service  :管理系统服务  本人在教学和实战过程中发现,即便是有一定运维经验的人,可能已经能够搭建一定复杂度的Linux架构,但是在来来回回的具体操作中,还是体现出CLI(命令界面)功底不够扎实,甚至操作的非常‘拙’、处处露‘怯’。 对一个士兵来说,枪就是他的武器,对于一个程序员来说,各种library(工具库)就是他的武器;而对于Linux运维人员来说,无疑命令行工具CLI(命令界面)就是他们的武器;高手和小白之间的差距往往就体现在对于这些“武器”的掌握和熟练程度上。有时候一个参数就能够解决的事情,小白们可能要写一个复杂的Shell脚本才能搞定,这就是对CLI(命令界面)没有理解参悟透彻导致。 研磨每一个命令就是擦拭手中的作战武器,平时不保养不理解,等到作战的时候,一定不能够将手中的武器发挥到最好,所以我们要平心、静气和专注,甘坐冷板凳一段时间,才能练就一身非凡的内功! 本教程从实战出发,结合当下流行或最新的Linux(v6/7/8 版本)同时演示,将命令行结合到解决企业实战问题中来,体现出教学注重实战的务实精神,希望从事或未来从事运维的同学,能够认真仔细的学完Linux核心命令的整套课程。 本课程系列将逐步推出,看看我教学的进度和您学习的步伐,孰占鳌头! 注:关于教学环境搭建,可以参考本人其它课程系列,本教学中就不再赘述! 《参透 VMware 桌面级虚拟化》 《在虚拟机中安装模版机(包括应用软件等)》 《SecureCRT 连接 GNS3/Linux 的安全精密工具》

69,375

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧