LINUX系统编程 关于SDTIO库缓冲区

简介: 我们知道标准C中的文件读取的函数比如printf,fwrite等函数,实际都是调用OS级别的 API,比如LINUX下就是wirte,read函数,而write read函数在用户态下是没有缓冲的, 当然在内核态有OS CACHE/OS BUFFER,所以某些...

我们知道标准C中的文件读取的函数比如printf,fwrite等函数,实际都是调用OS级别的
API,比如LINUX下就是wirte,read函数,而write read函数在用户态下是没有缓冲的,
当然在内核态有OS CACHE/OS BUFFER,所以某些直接调用wirte,read的程序肯定会
分配一个缓冲区,特别是O_DIRECT这种方式下,内核态的OS CACHE和OS BUFFER没用
这种情况下用户态的BUFFER显得更加重要,因为不可能一次读一个字节吧,那性能可想而知


而作为用户态空间的STDIO也是这样做的,它会为打开的文件分配缓存,默认应该是8192字节
如下图摘自UNIX系统编程手册 13章:


实际上我们可以使用setvbuf来设置某个打开文件的缓冲大小及模式。
我们来看看原型:
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
返回0为成功,非零为失败
FILE *stream:打开文件的FILE*
char *buf:BUFFER的地址,如果为NULL,MODE为_IOLBF和_IOFBF则自动分配缓冲区
           如果为_IONBF则不分配缓冲区
int mode:_IONBF不使用缓冲区,立即调用write/read,忽略buf和size为NULL和0,stderr属于这个
          _IOLBF使用行缓冲I/O,终端设备默认为这种。要么遇到换行符要么缓冲满才调用write/read,
          stdin/stdout属于这个。
          _IOFBF采用全缓冲I/O,buffer满才调用write/read,磁盘I/O属于这个比如fwrite/fread
size_t size:缓冲大小


更简单函数setbuf原型如下:
void setbuf(FILE *stream, char *buf);
相当于
setvbuf(fp,buf,(buf !=NULL)?_IOFBF:_IONBF,BUFSIZ);


如果buf=NULL则_IONBF打开不带缓冲,或者调用全缓冲,BUFSIZ默认8192。
所以我们如果不想用缓冲直接:
setvbuf(fp,NULL)
即可。


现在回想一下fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);


fread的时候我们通常要calloc一块内存用于void *ptr,那么现在我们想一下实际
上这个数据正常缓存到了3个地方
1、用户分配的内存*ptr
2、STDIO的缓存默认8192
3、内核态OS CACHE
这视乎有点臃肿,我们可以想办法简化。事实上数据库软件有时候只使用了用户态
的一份缓存,而打开O_DIRECT来提高性能。


下面一个小程序可以验证打开和关闭stdout缓冲的区别:


int main(void)
{
        int i;
//      setbuf(stdout,NULL);


        for(i=0;i<10;i++)
        {
                printf("-");
                sleep(1);
        }


        printf("\n");
}


区别就是是否使用setbuf,如果使用setbuf则 -符号会一个一个输出,不使用会一起输出
这就是STDIO缓存在作怪。
相关文章
|
23天前
|
Linux系统之whereis命令的基本使用
Linux系统之whereis命令的基本使用
57 23
Linux系统之whereis命令的基本使用
|
23天前
|
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
45 17
|
3月前
|
Linux缓存管理:如何安全地清理系统缓存
在Linux系统中,内存管理至关重要。本文详细介绍了如何安全地清理系统缓存,特别是通过使用`/proc/sys/vm/drop_caches`接口。内容包括清理缓存的原因、步骤、注意事项和最佳实践,帮助你在必要时优化系统性能。
284 78
|
1月前
|
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
54 26
Linux系统查看操作系统版本信息、CPU信息、模块信息
在Linux系统中,常用命令可帮助用户查看操作系统版本、CPU信息和模块信息
142 23
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
132 13
安装【银河麒麟V10】linux系统--并挂载镜像
安装【银河麒麟V10】linux系统--并挂载镜像
2837 0
卸载、下载、安装mysql(Linux系统centos7)
卸载、下载、安装mysql(Linux系统centos7)
288 0
|
5月前
|
手把手教会你安装Linux系统
手把手教会你安装Linux系统
125 0
部署05-VMwareWorkstation中安装CentOS7 Linux操作系统, VMware部署CentOS系统第一步,下载Linux系统,/不要忘, CentOS -7-x86_64-DVD
部署05-VMwareWorkstation中安装CentOS7 Linux操作系统, VMware部署CentOS系统第一步,下载Linux系统,/不要忘, CentOS -7-x86_64-DVD
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等