Linux系统函数查看流对象是行缓冲还是全缓冲还是无缓冲
有关全/行/无缓冲的区别
在《UNIX环境高级编程》第三版131页有这么个程序(已化简)
# include <unistd.h>
# include<stdio.h>
# include<error.h>
# include <stdlib.h>
# include <errno.h>
# ifdef _IONBF//等同于 #if define(_IONBF)
int is_unbuffered(FILE *fp)
{
return((fp->_flags)&_IONBF);
}
int is_linebuffed(FILE *fp)
{
return((fp->_flags)&_IOLBF);
}
int buffer_size(FILE *fp)
{
return (fp->_IO_buf_end-fp->_IO_buf_base);//return buff size
}
#else
#error unknown stdio implementation
#endif
void pr_stdio(const char * name, FILE * fp)
{
printf("stream=%s ",name);
if(is_unbuffered(fp))
{
printf("unbuffered");
}
else if(is_linebuffed(fp))
{
printf("line buffered");
}
else
{
printf("fully buffered");
}
printf(", buffer size = %d\n", buffer_size(fp));
}
int main(int argc,char *argv[])
{
fputs("enter any character\n",stdout);
if(getchar()==EOF)
{
printf("get char error\n");
}
fputs("one line to standard error\n",stderr);
pr_stdio("stdin",stdin);
pr_stdio("stdout",stdout);
pr_stdio("stderr",stderr);
return 0;
}
其原理是利用FILE结构体的flags来判断该IO流是全、行、无缓冲的哪一个。
但是执行结果确是
这明显是不对的,因为我们都知道,标准输入流(stdin)和标准输出流(stdout)都是行缓冲(这个无可争议,我也试过了,ubuntu20上确实是行缓冲),标准错误是无缓冲,这个是对的。
我们自定义一个文件描述符(默认应该是全缓冲),然后分别用setlinebuf()和setvbuf设置其为行缓冲和无缓冲,然后在debug模式观察flags标识位
FILE * stc=fopen("log.txt","a");
pr_stdio("stc",stc);//全缓冲
setlinebuf(stc);
pr_stdio("stc",stc);//行缓冲
char *buf;
setvbuf(stc,buf,_IONBF,4096);
pr_stdio("stc",stc);//无缓冲
运行结果为
全缓冲结构体数据
行缓冲结构体数据
无缓冲结构体数据
转化为二进制比较
一个0x484(全缓冲),一个0x684(行缓冲),一个0x487(无缓冲),我们对上述进行分析,然后重新写判断函数,经过我们分析了stdout,stderr的flags位后,发现,如果是行缓冲,需要0x200,如果是无缓冲,需要0x1
修改判断函数如下:
int is_unbuffered(FILE *fp)//判断是否无缓冲
{
return((fp->_flags)&0x1);
}
int is_linebuffed(FILE *fp)//判断是否行缓冲
{
return((fp->_flags)&0x200);
}
最终程序如下:
# include <unistd.h>
# include<stdio.h>
# include<error.h>
# include <stdlib.h>
# include <errno.h>
# ifdef _IONBF
int is_unbuffered(FILE *fp)
{
return((fp->_flags)&0x1);
}
int is_linebuffed(FILE *fp)
{
return((fp->_flags)&0x200);
}
int buffer_size(FILE *fp)
{
return (fp->_IO_buf_end-fp->_IO_buf_base);//return buff size
}
#else
#error unknown stdio implementation
#endif
void pr_stdio(const char * name, FILE * fp)
{
printf("stream=%s ",name);
if(is_unbuffered(fp))
{
printf("unbuffered");
}
else if(is_linebuffed(fp))
{
printf("line buffered");
}
else
{
printf("fully buffered");
}
printf(", buffer size = %d\n", buffer_size(fp));
}
int main(int argc,char *argv[])
{
fputs("enter any character\n",stdout);
if(getchar()==EOF)
{
printf("get char error\n");
}
fputs("one line to standard error\n",stderr);
FILE * stc=fopen("log.txt","a");
pr_stdio("stc",stc);
char *buf;
setlinebuf(stc);
//setvbuf(stc,buf,_IONBF,4096);
pr_stdio("stc",stc);
setvbuf(stc,buf,_IONBF,4096);
pr_stdio("stc",stc);
pr_stdio("stdin",stdin);
pr_stdio("stdout",stdout);
pr_stdio("stderr",stderr);
return 0;
}
执行结果:
符合要求