V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
ltzliwe
V2EX  ›  问与答

关于vfork的问题。。

  •  
  •   ltzliwe · 2011-12-04 22:27:01 +08:00 · 4199 次点击
    这是一个创建于 4737 天前的主题,其中的信息可能已经有所发展或是发生改变。
    这是一个错误的程序, 但是为什么我只调用了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 条回复    1970-01-01 08:00:00 +08:00
    ltzliwe
        1
    ltzliwe  
    OP
       2011-12-04 22:35:00 +08:00
    没人回答吗。。。。help
    samuel
        2
    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
        3
    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
        4
    raptium  
       2011-12-05 00:06:40 +08:00
    咦 糊涂了 child process 没有从 f1 return,不过还是 call 了 exit(3) ,所以导致诡异情况也不出奇了
    ltzliwe
        5
    ltzliwe  
    OP
       2011-12-07 11:07:47 +08:00
    @raptium @samuel 额, 我错了。 应该去掉f1函数里的
    if(pid==0)
    exit(0);
    才会出现调用3次的结果。。 子进程在推出了f1之后应该把那个堆栈销毁了吧?
    我是在linux上跑的
    raptium
        6
    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
        7
    ltzliwe  
    OP
       2011-12-07 12:36:56 +08:00
    @raptium 大致晓得了。。 非常感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2534 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 01:46 · PVG 09:46 · LAX 17:46 · JFK 20:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.