Chinaunix

标题: 抓狂了,为啥会输出两次 [打印本页]

作者: welf    时间: 2010-05-21 16:23
标题: 抓狂了,为啥会输出两次
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5.         printf("%d", getpid());
  6.         switch (fork()) {
  7.                 case (-1):
  8.                         return -1;

  9.                 case (0):
  10.                         sleep(3);
  11.                         break;

  12.                 default:
  13.                         break;
  14.         }
  15. }
复制代码
如上代码,第一次输出pid后,3秒后又会输出一次,为什么为什么
作者: okocha-jay    时间: 2010-05-21 16:42
printf("%d\n", getpid());试试吧
作者: empty141    时间: 2010-05-21 16:47
加个换行符试试:
  1. printf("%d\n", getpid());
复制代码

作者: xiexiecn    时间: 2010-05-21 16:49
这是因为printf是有缓存的。printf之后fflush(stdout)就不会了。
作者: bill15    时间: 2010-05-21 16:51
加上\n就正常了

我觉得是进程内部调度和输出之间协调的问题,
进程先getpid,然后把"printf 进程号"送到标准输出
这时它就fork了,然后把"printf 进程号"也复制到子进程了

可能是这样,说不清,盼高手


作者: bill15    时间: 2010-05-21 16:52
这是因为printf是有缓存的。printf之后fflush(stdout)就不会了。
xiexiecn 发表于 2010-05-21 16:49



    恩,应该是这样
作者: xiexiecn    时间: 2010-05-21 16:55
这些缓存是库做的,当程序退出的时候会做一次fflush,所以最后你还会看到一次输出。
作者: sleetboy    时间: 2010-05-21 16:55
提示: 作者被禁止或删除 内容自动屏蔽
作者: welf    时间: 2010-05-21 16:55
回复 2# okocha-jay


加了之后,把标准输出重定向到文件,依旧是两行

我的原始问题就是,输出到终端,看到正常的输出,如果重定向到文件,看到的是重复两次的输出
作者: empty141    时间: 2010-05-21 16:58
标准输出是行缓存,文件是全缓存的
作者: churchmice    时间: 2010-05-21 17:07
fflush不可靠,用setbuf好

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main ()
  4. {
  5.   setbuf (stdout, NULL);
  6.   printf ("%d", getpid ());
  7.   switch (fork ())
  8.     {
  9.     case (-1):
  10.       return -1;

  11.     case (0):
  12.       sleep (3);
  13.       break;

  14.     default:
  15.       break;
  16.     }
  17. }

复制代码

作者: welf    时间: 2010-05-21 17:11
okey,明白了
输出两次是由于父进程退出时fflush了一次,子进程退出后又把同一块缓冲fflush了,于是就这样了
作者: 奶茶dsk    时间: 2010-05-21 17:24
额,stdout默认是行缓冲的,,没用newline,,进程exit的时候会fflush,,
作者: tianxiaogang12    时间: 2010-05-21 20:50
看来你的看看 apue第8章,173,174页,
1。没有加\n时printf是行缓冲,就不会打印出来,保留在缓冲区,在fork后子进程copy父进程空间(记住是全   
     copy包括缓冲区),这样父子空间都有pid这个值
2。 在printf里加了\n后,直接打印时没有没有问题的,但是你重定向在一个文件,这时不再是行缓冲了,而是全缓冲了,这样在printf调用后不会马上输出来,还是保留在缓冲区了,fork后子进程还是copy了父进程的缓冲区,这样就输出两次了
作者: jinyuliang    时间: 2010-05-21 21:31
上周才从 APUE 里面看到缓存这些事情,果然是很神奇……
作者: rain_fish    时间: 2010-05-21 21:46
回复 14# tianxiaogang12


    赞!学习了。。。。
作者: BMW_325i    时间: 2010-05-22 17:26
刚好看到APUE里相关的内容,长见识了,呵呵…………
作者: pengjianbokobe    时间: 2010-05-22 20:29
fflush不可靠,用setbuf好
churchmice 发表于 2010-05-21 17:07



    为什么fflush不可靠??
作者: Magic_LP    时间: 2010-05-22 23:30
缓冲的原因,子进程从父进程“复制”了这部分数据,当进程退出时,冲洗所有的缓冲区,导致输出。
换成printf("%d\n", getpid());
因为标准输出是行缓冲,在fork前就冲洗缓冲区,这样子进程就继承不到这部分数据了。就只会输出一次
作者: logicBaby    时间: 2010-05-23 03:07
明显缓存的事儿,直接用write吧。
作者: _cer    时间: 2010-05-23 11:01
学习了
作者: TMBest    时间: 2010-05-24 16:51
这是因为printf是有缓存的。printf之后fflush(stdout)就不会了。
xiexiecn 发表于 2010-05-21 16:49


学习了
作者: sithui    时间: 2010-05-24 16:57
提问之前搜一下旧帖,这个问题记得问过好几次了
作者: hnynes    时间: 2010-05-25 13:14
嗯,又学习了。呵呵 。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2