一个关于fork进程的问题

chinaljj 2005-08-12 04:10:04
很简单的一段代码:
#include <stdio.h>

int main(int argc , char **argv)
{
int i;
int pid;

for ( i = 0 ; i < 3; i++ )
{
if ( (pid = fork()) == 0 )
{
printf("# Parent : %d # Child : %d ## fork print is : %d\n" , getppid() ,
getpid() , i);
}
}
}
该程序编译运行后结果如下:
[sybase]/export/home/sybase/lrj/bin> fork_test
# Parent:9228 # Child:9229 ## fork print is : 0
# Parent:9228 # Child:9230 ## fork print is : 1
# Parent:9228 # Child:9231 ## fork print is : 2
[sybase]/export/home/sybase/lrj/bin> # Parent:9229 # Child:9232 ## fork print is
: 1
# Parent:9230 # Child:9233 ## fork print is : 2
# Parent:9229 # Child:9234 ## fork print is : 2
# Parent:9232 # Child:9235 ## fork print is : 2
(不出现命令行提示符,光标停在此处)

并且每次运行该程序结果不一样。

本人很想知道的是:这个程序(主要是fork()调用)的运行机制到底是怎样的,才会出现上述的结果?
...全文
410 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
chinaljj 2005-08-17
  • 打赏
  • 举报
回复
不好意思,有些回帖的同志没有给分,主要是我的分少了些,望大家见谅!

再次多谢支持!
chinaljj 2005-08-17
  • 打赏
  • 举报
回复
very good !

谢谢大家的热心帮助!

结帖了!呵呵!
jerry 2005-08-16
  • 打赏
  • 举报
回复
子进程会完全克隆主进程。这样每个子进程都会继续循环下去继续产生新的子进程。于是你就出来了很多消息。我也初学。
chinaljj 2005-08-16
  • 打赏
  • 举报
回复
krh2001(边城浪子),你说的是。

但能否进一步解释一下我上面的两个问题?

我理解:即便子进程没有结束,可子进程的动作只有printf,而整个程序也就循环3次,我理解是fork了三个进程,应该只有三条print信息才是呀?

还有,子进程没有结束,那么fork出的子进程在printf后处于什么状态呢?

无知得很,多指教,别见笑!
jerry 2005-08-16
  • 打赏
  • 举报
回复
子进程没有结束。

#include <stdio.h>

int main(int argc , char **argv)
{
int i;
int pid;

for ( i = 0 ; i < 3; i++ )
{
if ( (pid = fork()) == 0 )
{
printf("# Parent : %d # Child : %d ## fork print is : %d\n" , getppid() ,
getpid() , i);
exit(0);
}
}
}
chinaljj 2005-08-16
  • 打赏
  • 举报
回复
自己顶!
liqiuhua123 2005-08-16
  • 打赏
  • 举报
回复
这个问题我分析了一下,确实挺有意思的。
子进程会完全克隆主进程,这每个人都很清楚。
这样每个子进程都会继续循环下去继续产生新的子进程,这也是对的,但为什么会产生楼主所示的情况呢,我认为可能是一下原因:
首先第一个进程(父进程,楼主的是9228进程),在第一次循环它会产生一个子进程(9229)这时就出现了第一条打印信息。接着9229将继承9228的一切,包括资源(例如变量i的值),这时i=1,这是9228和9229会同时做一件事(继续循环创建子进程,i是从1开始的),他们分别创建了9230、9232这两个子进程,于是就出现了第二条和第四条打印信息(# Parent:9228 # Child:9230 ## fork print is : 1 # Parent:9229 # Child:9232 ## fork print is
: 1)。接着会有4个进程做同样的事情,(这时i已经等于2了,是最后一次循环了),他们又分别创建了四个子进程(9231,9233,9324,9235)。接着整个程序就运行完了。至于命令行跑到中间,光标停在最后不动了,那都是标准输出缓冲的问题,跟这个程序没有一点关系。虽然每次结果不同,但是你们可以发现一些规律,就是9228创建了三个进程(因为循环了三次),9229创建了两个进程(循环了两次),9230和9232分别创建了一个进程。因为是并行的,所以顺序有时候会不一样。
chinaljj 2005-08-15
  • 打赏
  • 举报
回复
你(bekars(涡轮增压))说:
“父进程创建了子进程9232之后,9232又变成父进程产生子进程9235,直到i的值增加到3,fork才结束。“
我想问:为什么父进程创建的子进程9232又会变成父进程而产生一个新的子进程9235?难道说在fork()后子进程连同父进程的for循环语句也一并复制过去了吗?

还有你说:
”如果系统没有机会执行父进程的++i的操作,这个fork递归执行下去。”
为什么fork会递归执行下去?能否进一步解释一下?
chinaljj 2005-08-15
  • 打赏
  • 举报
回复
我很想再请问一下bekars(涡轮增压) :

对于多进程编程,我还是有一定了解的,但就我提的这个问题而言,我的理解是这样的:
虽然i的值被子进程复制了,但这个简单的程序应该只创建了三个子进程,由于在for循环中指定了条件if ( (pid = fork()) == 0 ),而printf语句在这样的条件下应该是在子进程中才会被执行,在父进程中根本没有printf语句进行输出,那么为什么会有那么多条输出信息?

不知我的理解什么地方有错误,还请不吝赐教!
fytzzh 2005-08-13
  • 打赏
  • 举报
回复
光标肯可能是因为主进程比子进程先退出.
在子进程里 printf("# Parent : %d # Child : %d ## fork print is : %d\n" , getppid() ,
getpid() , i); 这个i的值是创建子进程时对父进程的拷贝.
子进程里的i和主进程里的i是两回事. 也就是说父进程中的i改变了,不会改变子进程中的i.
hundlom 2005-08-13
  • 打赏
  • 举报
回复
fork后,会有两个进程运行。父进程和子进程都运行!
更仔细全面的请看《高级环境编程》
bekars 2005-08-13
  • 打赏
  • 举报
回复
子进程被创建之后把所有父进程的数据都作一份拷贝,并且继续向下执行,注意下面的打印,
父进程创建了子进程9232之后,9232又变成父进程产生子进程9235,直到i的值增加到3,fork才结束。
如果系统没有机会执行父进程的++i的操作,这个fork递归执行下去。
所以在创建子进程之后父进程一般会退出或者等待。

[sybase]/export/home/sybase/lrj/bin> # Parent:9229 # Child:9232 ## fork print is
: 1
# Parent:9230 # Child:9233 ## fork print is : 2
# Parent:9229 # Child:9234 ## fork print is : 2
# Parent:9232 # Child:9235 ## fork print is : 2
zsb1107 2005-08-12
  • 打赏
  • 举报
回复
看看源代码中的fork.c文件,尤其是其中的find_empty_process()函数就会清楚了。
当pid大于零时,这时要执行的是父进程代码,但pid的值是子进程的进程号。
当pid等于0时,要执行的是子进程代码。
一个父进程可以有好多子进程,这就是为何parent都是9228的缘故。
看过find_empty_process()函数就会发现,子进程的进程号是通过++last_pid得到的,这就是为何三个子进程的进程号分别为9229、9230、9231的缘故。
asphp 2005-08-12
  • 打赏
  • 举报
回复
fork 完后,会克隆一个新一进程,新进程的资源(包括变量)都会照原程序的样子COPY一份(除了 fork()的返回值不同),然后如果是子进程的话,fork()的返回值为0 如果是父进程 返回的是子进程的进程号。

23,116

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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