免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1970 | 回复: 7
打印 上一主题 下一主题

vfork exit _exit [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-06-03 17:45 |只看该作者 |倒序浏览
大家好,我是新手。请大家看代码:

#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int     glob = 6;       /* external variable in initialized data */

int
main(void)
{
    int     var;        /* automatic variable on the stack */
    pid_t   pid;

    var = 88;
    printf("before vfork\n");   /* we don't flush stdio */
    if ((pid = vfork()) < 0) {
        printf("vfork error");
    } else if (pid == 0) {      /* child */
        glob++;                 /* modify parent's variables */
        var++;
        exit(0);               /* child terminates */
    }
    /*
     * Parent continues here.
     */
    printf("pid = %d, glob = %d, var = %d", getpid(), glob, var);
    _exit(0);
}
执行结果:before vfork
pid = 15948, glob = 7, var = 89


请问:父进程的最后一个printf为什么能打印出来呢?

论坛徽章:
0
2 [报告]
发表于 2012-06-03 22:07 |只看该作者
LZ,把child 里面的exit(0)改成_exit(0)。就会得到你想要的了.
如下:子进程的printf就不会输出了。
至于原因,我猜可能是因为exit可能在内部有判断,发现是vfork这样的时候,则fd = 0和1 , 2就不会关闭了(*可能*就没调用_exit)。所以如果直接用_exit的话,就会把共用的fd = 0 , 1 , 2都关闭,最后父进程的1,已经被close了, 故printf无输出了。   **猜测**
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int     glob = 6;       /* external variable in initialized data */

int
main(void)
{
    int     var;        /* automatic variable on the stack */
    pid_t   pid;
       
    var = 88;
    printf("before vfork\n");   /* we don't flush stdio */
    if ((pid = vfork()) < 0) {
        printf("vfork error");
    } else if (pid == 0) {      /* child */
        glob++;                 /* modify parent's variables */
        var++;
        _exit(0);               /* child terminates */
    }
    /*
     * Parent continues here.
     */
    printf("pid = %d, glob = %d, var = %d", getpid(), glob, var);
        _exit(0);
       
}
你试试,

论坛徽章:
0
3 [报告]
发表于 2012-06-03 22:15 |只看该作者
回复 2# fdl19881


    感谢你的回帖,我验证的结果是你说的对,如果都用_exit,是不会输出,但是如果把最后一个printf后面加上"\n",依然会输出,所以问题依然没有解决,exit并没有关闭标准输入输出,我好奇的是,如果按照我的原先程序,最后父进程_exit(),并不会刷新标准输入输出流,所以最后一个printf应该不打印才对啊。。为什么就打印了呢?原先程序中把vfork改成fork则最后一个printf不会打印出来。这是为什么呢?

论坛徽章:
0
4 [报告]
发表于 2012-06-03 22:25 |只看该作者
回复 3# ooaoodoop1


    确定用_exit还是没关闭描述符。 我觉得会不会是 在vfork的时候和fork一样, 就是文件描述符对应的 *文件表* 的引用计数也+1了。就像fork时,文件描述符得使用两次close才能完全关闭一样(比如对于fork后继承的socket套接字就是这种情况,父进程和子进程都得close才会收发tcp套接口的fin分节发出 ). 验证如下:
父进程使用close关闭1后,子进程还是可以输出!!
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int     glob = 6;       /* external variable in initialized data */

int
main(void)
{
    int     var;        /* automatic variable on the stack */
    pid_t   pid;
       
    var = 88;
    printf("before vfork\n");   /* we don't flush stdio */
    if ((pid = vfork()) < 0) {
        printf("vfork error");
    } else if (pid == 0) {      /* child */
        glob++;                 /* modify parent's variables */
        var++;
                sleep(4);
                printf("haha\n");
        exit(0);               /* child terminates */
    }
    /*
     * Parent continues here.
     */
        close(1);
    //printf("pid = %d, glob = %d, var = %d", getpid(), glob, var);
        _exit(0);
       
}

论坛徽章:
0
5 [报告]
发表于 2012-06-03 22:32 |只看该作者
回复 4# fdl19881


    vfork永远是子进程先运行结束或者调用exe,否则父进程一直等待。。

论坛徽章:
0
6 [报告]
发表于 2012-06-04 00:46 |只看该作者
回复 5# ooaoodoop1


    那个说法和例子确实搞错了。

刚刚试了下, fd 0 , 1 , 2 不vfork_exit也不会关闭,这点不用怀疑。
我发现vfork如果结束时调用exit(), 那么缓冲方式就会改变。
(好像就是内部缓存为0了,不管用setvbuf(stdout , 0 , _IOLBF , 0)还是setvbuf(stdout , 0 , _IOFBF , 0)怎么设置都没用了。)
但是如果使用自己的缓存空间设置就可以 。 setvbuf(stdout , buff , _IOLBF , sizeof(buff))
所以我觉得这个现象是由于××标准IO库××的实现有关。。。。 vfork在exit后,使得标准IO对stdout的缓存方式变成了无缓存的样子了,并且无论怎么设置都无法使得里面的自带的缓存机制工作了。。
看这个例子如下:
#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
int     glob = 6;       /* external variable in initialized data */
char buff[1024];
int
main(void)
{
    int     var;        /* automatic variable on the stack */
    pid_t   pid;
        int ret;
        
    var = 88;
    printf("before vfork\n");   /* we don't flush stdio */
    if ((pid = vfork()) < 0) {
        printf("vfork error");
    } else if (pid == 0) {      /* child */
        glob++;                 /* modify parent's variables */
        var++;
        exit(0);               /* child terminates */
    }
    /*
     * Parent continues here.
     */
        /*以下三句三选一,然后看结果。*/
        ret = setvbuf(stdout , buff , _IOLBF , sizeof(buff)); //使用这句时,就无输出了。以下两句都还是有输出。但设置函数并没出错!
        //ret = setvbuf(stdout , 0 , _IOFBF , 0);
        //ret = setvbuf(stdout, NULL , _IOLBF, 0);
        if(ret != 0)
          pause();//这里用pause,以免引起混乱。
    printf("pid = %d, glob = %d, var = %d", getpid(), glob, var); //你可以加上\n验证下是不是我说的情况。
        _exit(0);   
}

应该就是这种情况了。

论坛徽章:
0
7 [报告]
发表于 2012-06-04 00:48 |只看该作者
在vfork()创建的子进程中调用 exit()会影响父进程的状态,产生未定义行为。
这就向那边的回复一样,  , 和glibc的实现方法有关了。

我的实验环境是ubuntu 12.04LTS

论坛徽章:
0
8 [报告]
发表于 2012-06-04 19:58 |只看该作者
回复 7# fdl19881


    应该是这样,我在ubuntu12.04中会有输出,但是在hp-unix中就不会有输出,因该是和实现有关,vfork是关闭文件描述符,只不过vfork和fork一样是copy文件描述符的(内存空间是共享的)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP