免费注册 查看新帖 |

Chinaunix

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

请教一个vfork的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-05 14:13 |只看该作者 |倒序浏览
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<sys/types.h>
  4. #include<unistd.h>

  5. int     glob = 6;

  6. int
  7. main(void)
  8. {
  9.         int     var;
  10.         pid_t   pid;

  11.         var = 88;
  12.         printf("before vfork\n");

  13.         if((pid = vfork()) < 0){
  14.                 printf("vfork error\n");
  15.                 exit(EXIT_FAILURE);
  16.         }else if(pid == 0){
  17.                 glob++;
  18.                 var++;
  19.                 exit(EXIT_SUCCESS);
  20.         }

  21.         /* parent */
  22.         int res;

  23.         res = printf("pid = %d, glob = %d, var = %d\n",
  24.                 getpid(), glob, var);

  25.         exit(EXIT_SUCCESS);
  26. }
复制代码
在看APUE的时候,看到vfork实例,书上说当子进程调用exit的时候,会执行标准I/O缓存的刷新操作并关闭所有打开的标准I/O流,
然后到父进程运行时,父进程调用printf函数,标准输出已经关闭了,所以printf打印不出信息。
    但是我执行这段代码的时候,父进程调用printf还是能打印信息:
    $ ./vfork
                    before vfork
                    pid = 12260, glob = 7, var = 89

到这里我就不太明白了为什么还可以打印出信息,难道exit函数没有关闭输出流?

论坛徽章:
0
2 [报告]
发表于 2011-01-05 17:31 |只看该作者
在创建进程的时候会dup父进程的文件描述符,相当于打开了两次流,关闭流只是把流引用数减一,流引用数为0时系统才会真正的关闭流。

论坛徽章:
0
3 [报告]
发表于 2011-01-05 19:12 |只看该作者
书上说vfork采用COW(写时复制技术)而并不像fork那样生成父进程的副本,请问“写时复制”可否理解为父进程代码执行到哪里,子进程就复制到哪里呢?

论坛徽章:
0
4 [报告]
发表于 2011-01-07 11:37 |只看该作者
$ ./vfork > test.file
这里最大的一个问题是:当子进程执行了exit()函数之后,
父进程执行到第二个printf时,同样会刷新缓存,把内容
写到文件里面。
对于文件,使用全缓存模式。
不同情况:
1、子进程调用exit函数,父进程调用_exit函数。结果:2个printf内容写到文件里面(不正常,应该只有第一个printf内容)
2、子进程调用_exit函数,父进程调用exit函数。结果:2个printf内容写到文件里面(正常)
3、子进程调用exit函数,父进程调用exit函数。结果:2个printf内容写到文件里面(正常)
4、子进程调用_exit函数,父进程调用_exit函数。结果:没有内容写到文件里面(正常)

论坛徽章:
0
5 [报告]
发表于 2011-01-07 14:58 |只看该作者
写时复制不是那个意思,本来fork之后子进程是父进程的一个副本,但是一般情况下子进程创建后会立即执行exec覆盖地址空间,所以复制纯属浪费,所以现在子进程创建时并不复制父进程的地址空间,而是公用,任何一个进程要修改进程空间时系统会复制一份给它,这叫写复制,如果两个进程都不修改那就不用复制了可以一直公用一份地址空间。在现在的fork也采用了写时复制,linux内核2。2以前其实两个系统调用是相同的,只是vfork保证子进程先运行。在vfork的情况下,子进程先运行,在本例中子进程结束后父进程才运行。子进程调用exit结束后父进程才得到执行的机会,随后打印下面的内容,然后调用_exit,进程结束,进程结束时内核会自动对缓冲区进行刷新。

论坛徽章:
0
6 [报告]
发表于 2011-01-07 17:39 |只看该作者
谢谢 pinkrobin
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP