linux文件io缓冲

出于速度和效率考虑,系统io调用(即内核)和标准 C语言库的io函数(即 stdin 函数)在操作磁盘文件时会对数据进行缓冲。

read(),write()系统调用在操作磁盘文件时不会直接发起磁盘访问,而是仅仅在用户空间缓冲区与内核缓冲区高速缓存( kemel buffer cache )之间复制数据。

例如,如下调用将 3 个字节的数据从用户空间内存传递到内核空间的缓冲区中

write ( fd , " abc " , 3 ) ;

write()随即返回。在后续某个时刻,内核会将其缓冲区中的数据写入(刷新至)磁盘。(因此,可以说系统调用与磁盘操作并不同步。)如果在此期间,另一进程试图读取该文件的这儿个字节,那么内核将自动从缓冲区高速缓存中提供这些数据,而不是从文件中(读取过期的内容)。

与此同理,对输入而言,内核从磁盘中读取数据并存储到内核缓冲区中。read()调用将从该缓冲区中读取数据,直至把缓冲区中的数据取完,这时,内核会将文件的下一段内容读入缓冲区高速缓存。(这里的描述有所简化。对于序列化的文件访问,内核通常会尝试执行预读,以确保在需要之前就将文件的下一数据块读入缓冲区高速缓存中。采用这一设计,意在使read()和write()操作更为快速,因为它们不需要等待(缓慢的)磁盘操作。同时,这一设计也极为高效,因为这减少了内核必须执行的磁盘传输次数。 Linux 内核对缓冲区高速缓存的大小没有固定上限。内核会分配尽可能多的缓冲区高速缓存页,而仅受限于两个因素:可用的物理内存总量,以及出于其他目的对物理内存的需求(例如,需要将正在运行进程的文本和数据页保留在物理内存中)。若可用内存不足,则内核会将一些修改过的缓冲区高速缓存页内容刷新到磁盘,并释放共系统重用。

stdio库的缓冲

当操作磁盘文件时,缓冲大块数据以减少系统调用,c语言函数库的io函数(fprintf()、fscanf()、fgets()、fputs()、fputc、fgetc())都是这么做的。因此,使用stdio库可以使编程者免于自行处理数据的缓冲。int setvbuf(FILE *stream, char *buf, int mode, size_t size);

//成功返回0

stream为要指定缓冲类型的文件流,mode如下表mode描述

_IONBF不缓冲,每个stdio库函数立即调用write()或read(),并且忽略buf,size参数。

_IOLBF行缓冲,遇到换行符就刷新缓冲数据,除非缓冲区提前满了。

_IOFBF全缓冲,缓冲区满了才刷新。

void setbuf(FILE *stream, char *buf);

//类似于setvbuf(fq, buf, (buf != NULL)?_IOFBF:_IONBF, BUFSIZ);

要么不缓冲,要么设置全缓冲,全缓冲的大小固定为BUFSIZ(8192)

void setbuffer(FILE *stream, char *buf, size_t size);

相较于setbuf这个setbuffer可以指定缓冲区的大小。

例子//不缓冲

setvbuf(stderr, NULL, _IONBF, 0);

setbuf(stderr, NULL);

setvbuf(stderr, NULL, _IOLBF, 1024); //系统分配缓冲内存1024

char *buf = malloc(1024);

setvbuf(stderr, buf, _IOLBF, 1024); //行缓冲到buf

//全缓冲,缓冲区大小固定为8192

char *buf = malloc(BUFSIZ);

setbuf(stderr, buf, BUFSIZ);

//全缓冲,缓冲区大小自定义为1024

char *buf = malloc(1024);

setbuffer(stderr, buf, 1024);

手动刷新stdio缓冲区

无论当前使用何种缓冲区模式,在任何时候,都可以使用fflush()库函数强制将stdio输出流中的数据(即write())刷新到内核缓冲区中。注意:不一定写入到磁盘,只是从用户空间复制到内核空间。#include

int fflush(FILE *stream);

若stream为NULL,则将刷新所有的stdio缓冲区。

当关闭流时,自动刷新缓冲区。

当fflush()函数应用于输入流时,这将丢弃已缓冲的输入数据。当程序下一次尝试从流中读取数据时,将重新装满缓冲区。

在包括glibc库在内的许多C函数库实现中,若stdin和stdout指向终端,那么无论何时从stdin中读取输入时,都将隐式调用一次fflush(stdout)函数。这将刷新写入stdout的任何提示,但不包括换行符。比如(printf("name:"))。然而c99并未规定,所以为了可移植性,最好手动调用fflush(stdout)。

上面只是控制用户空间的缓冲区,下面来看看如何控制内核缓冲区。

控制文件io的内核缓冲

强制刷新内核缓冲到输出文件是可能的,有时候也很有必要。int fsync(int fd);

//成功返回0

刷新文件数据,元数据(文件大小、修改时间、文件权限...)到磁盘。

int fdatasync(int fd);

//成功返回0

只刷新文件数据到磁盘,不包括元数据。

void sync(void);

刷新所有内核缓冲区(数据块、指针块、元数据等)到磁盘

使所有写入同步fd = open(pathname, O_WRONLY|O_SYNC);

每次wirte操作都会自动将文件数据和元数据刷新到磁盘。谨慎使用,会影响性能。

直接IO(direct io)

linux允许应用程序在执行磁盘io时绕过高速缓冲区,从用户空间直接将数据传递到文件或磁盘设备。

在open的时候指定O_DIRECT标志。因为直接io涉及到磁盘的直接访问,必须遵守一些限制

1.用于传递数据的缓冲区,器内存边界必须对齐为块大小的整数倍(可以利用posix_memalign)。

2.数据传输的开始点,亦即文件和设备的偏移量,必须为块大小的整数倍。

3.待传递数据的长度必须为块大小的整数倍。

注意:

对大多数程序而言,使用直接io会大大降低性能,因为内核针对缓冲区高速缓存做了不少优化,其中包括按顺序预读取,在成簇磁盘块上执行io,允许访问同一文件的多个进程共享高速缓存的缓冲区。如果使用了直接io则都无法受益于这些优化举措。直接io只适用于特定的应用如数据库系统,因为它的高速缓存,io优化都自己做了,那么就无需内核消耗cpu时间和内存去完成相同的任务。

混合使用库函数和系统调用进行文件ioint fileno(FILE *stream);

//成功返回文件描述符,错误返回-1

传入文件流,返回文件描述符,随即可以使用read()、write()、dup之类的系统调用来处理。

FILE *fdopen(int fd, const char *mode);

//失败返回NULL

这个方法与fileno的功能刚好相反,给定一个文件描述符,返回一个文件流指针。mode跟fopen函数中的mode参数含义相同。r为读,w为写,a为追加。

一般的用途是比如一般socket返回的都是文件描述符,可以通过fdopen()转化成支持stdio库的操作的文件流

也可以混合操作write,fprintf单数要注意缓冲的问题,write直接缓冲到内核,而fprintf会先缓冲在用户空间再到内核空间。

例子#include

#include

#include

#include

int

main(int argc, char *argv[])

{

char *url = "http://www.freecls.ocm ";

printf("stdio库");

write(STDOUT_FILENO, url, strlen(url));

return 0;

}

/*

http://www.freecls.ocm stdio库

*/

为啥会出现上述结果呢,因为stdio库的printf()会先缓冲到用户空间内存,待缓冲满时才会复制到内核缓冲区,而write会直接缓冲到内核空间。

为了规避这一问题,我们可以使用fflush()或使用setvbuf()或setbuf()来禁用缓冲区,单这样会影响到应用的性能,因为每个输出操作都将调用一次系统调用write()。#include

#include

#include

#include

int

main(int argc, char *argv[])

{

char *url = "http://www.freecls.ocm ";

printf("stdio库 ");

fflush(stdout);

write(STDOUT_FILENO, url, strlen(url));

return 0;

}

/*

stdio库 http://www.freecls.ocm

*/

linux的每次IO大小控制,linux文件io缓冲相关推荐

  1. linux的每次IO大小控制,Linux优化之IO子系统监控与调优

    Linux优化之IO子系统 作为服务器主机来讲,最大的两个IO类型 : 1.磁盘IO 2.网络IO 这是我们调整最多的两个部分所在 磁盘IO是如何实现的 在内存调优中,一直在讲到为了加速性能,linu ...

  2. Linux命令进阶-cpu监控内存监控文件IO网络IO性能分析

    Linux命令进阶-cpu监控内存监控文件IO网络IO性能分析 前言 1 linux基础命令 1.1 grep 1.2 ls 1.3 find 1.4 ulimit 1.5 curl 1.6 scp ...

  3. windows远程桌面linux系统,Windows远程桌面控制Linux图文详解

    随着互联网的高速发展以及Linux企业应用的成熟,Linux被广泛应用于服务器领域,如何实现Linux的远程管理成为网络管理员的首要任务. 我们经常见到的几种最为常用的windows下远程管理Linu ...

  4. linux空文件夹大小,[转载]linux 查看文件和文件夹大小

    Linux查看文件夹大小 du -sh 查看当前文件夹大小 du -sh * | sort -n 统计当前文件夹(目录)大小,并按文件大小排序 附送: du -sk filename 查看指定文件大小 ...

  5. linux下创建指定大小的空文件

    使用dd这个linux命令可以创建一定大小文件. linux创建文件命令:dd命令 把指定的输入文件拷贝到指定的输出文件中,并且在拷贝的过程中可以进行格式转换.语法: CODE:[Copy to cl ...

  6. linux如何删除指定大小以下的文件夹,Linux中定时删除超过指定大小的文件夹

    背景: 开发环境总是动不动就没有空间了, 大部分都是debug日志.所以有必要在日志很疯狂的时候,删除不必要的日志. 思路:一. 书写删除日志文件脚本: 定时任务执行.  但是有时候的日志是需要保存用 ...

  7. linux dev shm 的大小,使用linux的/dev/shm增强性能

    一.简介: linux的/dev/shm是一个使用虚拟内存的名为tmpfs的文件系统.虚拟内存资源由物理内存(RAM)和交换分区组成,这些资源是由内核中的虚拟内存子系统来负责分配和管理./dev/sh ...

  8. linux修改swap分区大小2GB,Linux下修改Swap分区大小

    据了解Linux下可以有两种方法创建交换空间,一种是创建交换分区,另一种是创建交换文件.本文记录的是创建交换文件的方法,因为我用的是这种方法.. 添加交换文件步骤: 1.找个地方创建一个.swap的文 ...

  9. linux虚拟磁盘管理pe大小6,Linux下磁盘的高级管理——LVM逻辑卷管理

    文章目录 逻辑卷是什么 逻辑卷的原理 逻辑卷的优点 lv的管理 lv的建立 xfs格式下lvm的拉伸 ext4下lvm的拉伸和缩减 lvm快照 lvm快照的原理和作用 快照的建立 lvm的删除 逻辑卷 ...

最新文章

  1. 自嘲尾款人、丁工人?今年双十一就没想让你做人
  2. 学python不会英语怎么办_Python学习 英语不好怎么办?这里有官方中文文档你看不看...
  3. Bootstrap 表单控件的尺寸
  4. The use specified as definer('root'@'%') does not exist的解决办法
  5. eNSP重装之后,启动路由器时注册失败
  6. 拥2180亿美元收入 苹果成全球最大IT企业
  7. 阿里P7架构师浅谈Java 的年薪 40W 是什么水平?
  8. 警告提示:Capturing ‘self‘ strongly in this block is likely to lead to a retain cycle
  9. oracle收回dba权限后的检查,Oracle RAC GI 权限 检查和修复 方法
  10. 模拟SPI驱动SD卡
  11. 青岛海尔供应商java面试_青岛某企业面试题(2019-11)
  12. Nacos 1.1.0发布,支持灰度配置和地址服务器模式
  13. css 所有选择器 实例与总结
  14. 百度地理围栏的一个坑
  15. Clementine简介
  16. 如何选择优秀的服务器托管商?
  17. 新浪微博中链接不能直接打开的最新解决方案
  18. 《C陷阱与缺陷》----第三章 语义陷阱
  19. JQuery实现的登陆注册页面表单
  20. 无法打开Win10计算机管理,win10我的电脑管理打不开怎么办_win10此电脑管理打不开如何修复...

热门文章

  1. 安全起见,这款 IDEA 插件赶紧删了吧!
  2. 皮一皮:家里出了个不孝子...
  3. 常用的JVM参数,你现在就记好!
  4. 我们自嘲的“码农”身份被官方实锤了!
  5. 一语点破 Java 中的静态 static 关键字
  6. Redis+Nginx+设计模式+Spring全家桶+Dubbo+阿里P7技术精选文档
  7. 为什么中国程序员工作不轻松,加班多?
  8. Spring Boot 应用迁移到 Java 11
  9. css文字背景虚化,通过实现背景模糊、文字颜色流光渐变、边框扩展等效果学习transition、transform、@keyframes等属性及伪元素的使用...
  10. opencv jni Android 实例笔记