This topic created in 5280 days ago, the information mentioned may be changed or developed.
这是一个错误的程序, 但是为什么我只调用了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);
}
7 replies • 1970-01-01 08:00:00 +08:00
 |
|
1
ltzliwe Dec 4, 2011
没人回答吗。。。。help
|
 |
|
2
samuel Dec 4, 2011
你是在什么系统上跑的。。OS X上的结果:
in f1,i=1,pid=0 in f1,i=2,pid=1812 Between f1 and f2
看起来只f1只跑了两次啊
|
 |
|
3
raptium Dec 4, 2011
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 了两次,最后导致混乱了吧
|
 |
|
4
raptium Dec 5, 2011
咦 糊涂了 child process 没有从 f1 return,不过还是 call 了 exit(3) ,所以导致诡异情况也不出奇了
|
 |
|
5
ltzliwe Dec 7, 2011
@ raptium @ samuel 额, 我错了。 应该去掉f1函数里的 if(pid==0) exit(0); 才会出现调用3次的结果。。 子进程在推出了f1之后应该把那个堆栈销毁了吧? 我是在linux上跑的
|
 |
|
6
raptium Dec 7, 2011
去掉了那句还真就出现3次了
用 gdb 调试了一下 观察到的情况如下 vfork 出来的子进程是和父进程共享内存包括堆栈的 子进程从 f1 中 return 的时候必定会 leave ret 这样已经影响到堆栈了 等父进程 return 的时候本来要 ret 去 0x400571 printf("betw... 的 可是因为堆栈被改过了 又跳去了0x400585 f1 于是就运行了第三次 (至于为啥会是这里我还是不明白) 这样本来是会无限循环的 可大概是因为堆栈破坏得离谱了 这次vfork不会成功(也看不到 error)
======== 根据 vfork 的 man vfork 了之后子进程不可以修改任何数据,不可以从当前函数中返回,必须调用 execvp* 系列函数或者 _exit(),否则产生的结果是未定义的。 所以目前观察到的情况是可以接受的
|