关于vfork的问题。。 - V2EX
ltzliwe

关于vfork的问题。。

  •  
  •   ltzliwe Dec 4, 2011 4816 views
    This topic created in 5293 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
    ltzliwe
        1
    ltzliwe  
    OP
       Dec 4, 2011
    没人回答吗。。。。help
    samuel
        2
    samuel  
       Dec 4, 2011
    你是在什么系统上跑的。。OS X上的结果:

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

    看起来只f1只跑了两次啊
    raptium
        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 了两次,最后导致混乱了吧
    raptium
        4
    raptium  
       Dec 5, 2011
    咦 糊涂了 child process 没有从 f1 return,不过还是 call 了 exit(3) ,所以导致诡异情况也不出奇了
    ltzliwe
        5
    ltzliwe  
    OP
       Dec 7, 2011
    @raptium @samuel 额, 我错了。 应该去掉f1函数里的
    if(pid==0)
    exit(0);
    才会出现调用3次的结果。。 子进程在推出了f1之后应该把那个堆栈销毁了吧?
    我是在linux上跑的
    raptium
        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(),否则产生的结果是未定义的。
    所以目前观察到的情况是可以接受的
    ltzliwe
        7
    ltzliwe  
    OP
       Dec 7, 2011
    @raptium 大致晓得了。。 非常感谢
    About     Help     Advertise     Blog     API     FAQ     Solana     4937 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 51ms UTC 05:40 PVG 13:40 LAX 22:40 JFK 01:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86