关于vfork的问题。。

2011-12-04 22:27:01 +08:00
 ltzliwe
这是一个错误的程序, 但是为什么我只调用了vforkv一次但是f1()函数却执行了3遍呢?

#include<stdio.h>
#include<unistd.h>

static void f2(void);
static void f1(void);
int i=0;
int
main(void)
{
f1();
printf("Between f1 and f2\n");
exit(0);
}

static void
f1(void)
{
pid_t pid;

if ((pid = vfork()) < 0)
printf("vfork error");
printf("in f1,i=%d,pid=%d\n",++i,pid);
if(pid==0)
exit(0);
}
4096 次点击
所在节点    问与答
7 条回复
ltzliwe
2011-12-04 22:35:00 +08:00
没人回答吗。。。。help
samuel
2011-12-04 22:43:16 +08:00
你是在什么系统上跑的。。OS X上的结果:

in f1,i=1,pid=0
in f1,i=2,pid=1812
Between f1 and f2

看起来只f1只跑了两次啊
raptium
2011-12-04 23:56:08 +08:00
vfork() differs from fork(2) in that the parent is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Until that point, the child shares all memory with its parent, including the stack. The child must not return from the current function or call exit(3), but may call _exit(2).

大概是你的 child process 从 f1 return ,导致 ret 执行了两次 stack pop 了两次,最后导致混乱了吧
raptium
2011-12-05 00:06:40 +08:00
咦 糊涂了 child process 没有从 f1 return,不过还是 call 了 exit(3) ,所以导致诡异情况也不出奇了
ltzliwe
2011-12-07 11:07:47 +08:00
@raptium @samuel 额, 我错了。 应该去掉f1函数里的
if(pid==0)
exit(0);
才会出现调用3次的结果。。 子进程在推出了f1之后应该把那个堆栈销毁了吧?
我是在linux上跑的
raptium
2011-12-07 12:00:34 +08:00
去掉了那句还真就出现3次了

用 gdb 调试了一下 观察到的情况如下
vfork 出来的子进程是和父进程共享内存包括堆栈的
子进程从 f1 中 return 的时候必定会 leave ret 这样已经影响到堆栈了
等父进程 return 的时候本来要 ret 去 0x400571 printf("betw... 的
可是因为堆栈被改过了 又跳去了0x400585 f1 于是就运行了第三次 (至于为啥会是这里我还是不明白)
这样本来是会无限循环的 可大概是因为堆栈破坏得离谱了 这次vfork不会成功(也看不到 error)

========
根据 vfork 的 man
vfork 了之后子进程不可以修改任何数据,不可以从当前函数中返回,必须调用 execvp* 系列函数或者 _exit(),否则产生的结果是未定义的。
所以目前观察到的情况是可以接受的
ltzliwe
2011-12-07 12:36:56 +08:00
@raptium 大致晓得了。。 非常感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/22806

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX