[转]关于行缓冲区


今天看到CU上C版的有朋友代码及输出结果是这样的
#include <stdio.h> 

main() 
        printf("1."); 
        sleep(2); 
        printf("2."); 
        sleep(2); 
        printf("3."); 
        sleep(2); 
        printf("4."); 
        printf("OK\n"); 
%gcc test.c 
%./a.out 
1.2.3.4.OK

sleep没起到作用,而是这些1.2.3.4过了好一会一起输出了。
我试了一下,果然是这样,gcc编译的
看楼下高人们的说法是因为行缓冲,系统会把一行的数据一起输出,而不是打印一点,就输出一点。呵呵
标准输出是带有行缓冲的,解决办法有好几种:
我在每个后面加了换行,问题就没有了
[ktktkt@Jintao COMMON]$ cat 1.c
#include <stdio.h>

int main()
{
        printf("1\n");
        sleep(2);
        printf("2\n");
        sleep(2);
        printf("3\n");
        sleep(2);
        printf("4\n");
        sleep(2);
        printf("5\n");
        sleep(2);

        return 0;
}
这样由于有了换行,就不再一起输出了:)
[ktktkt@Jintao COMMON]$ ./1
1
2
3
4
5

还有解决办法是,在没有\n换行时,在每行后面强制刷新
[ktktkt@Jintao COMMON]$ cat 1.c
#include <stdio.h>

int main()
{
        printf("1 ");
        fflush(stdout);
        sleep(2);
        printf("2 ");
        fflush(stdout);
        sleep(2);
        printf("3 ");
        fflush(stdout);
        sleep(2);
        printf("4 ");
        fflush(stdout);
        sleep(2);
        printf("5 ");
        fflush(stdout);
        sleep(2);
        
        return 0;
}

结果是这样的:
[ktktkt@Jintao COMMON]$ ./1
1 2 3 4 5 
的确是两秒两秒输出的,蛮爽~
这个小tip蛮过瘾~

但是问题在于编译时指定-Wall仍然会有warning提示:
sleep函数没有?
[ktktkt@Jintao COMMON]$ gcc 1.c -o 1 -Wall
1.c: In function `main':
1.c:7: warning: implicit declaration of function `sleep'

man了一下
#man 3 sleep
发现是unistd.h里边的,于是加上这一行,再编译,没有问题了:),代码变成下面这样:

#include <stdio.h>
#include <unistd.h>

int main()
{
        printf("1 ");
        fflush(stdout);
        sleep(2);
        printf("2 ");
        fflush(stdout);
        sleep(2);
        printf("3 ");
        fflush(stdout);
        sleep(2);
        printf("4 ");
        fflush(stdout);
        sleep(2);
        printf("5 ");
        fflush(stdout);
        sleep(2);
        
        return 0;
}
这样就编译成功了...

flw老大的解释:
解决的办法有以下几种: 
1,改用 printf( "1\n" ) 但是这种方法有时候是作者不愿意的。 
2,改用 fprintf( stderr, "1" ) 因为 stderr 不是行缓冲的,所以可以这么做。我就经常采用这种方法,但是这种方法在输出重定向的时候,是要特别处理的,换句话说,它不符合和 shell 交互的某些规范。开发出来的程序不符合 shell 过滤器的习惯。 
3,改用 printf( "1\n" ) + fflush(stdout) 这是唯一的一种既不影响作者原意,又可以产生预期的效果的方法。说严格点,这是唯一正确的方法,因为这种方法不会影响到任何人、任何事。 
4,直接用某种手段修改你的 stdout 的属性,使之变成非行缓冲的,比如调用 ioctl 等系统调用或者是用操作系统提供的命令……

没有评论: