1.流与FILE对象

unix I/O系统调用都是针对文件描述符的
标准C的I/O函数都是针对流(文件指针)的,我们使用一个流与一个文件相关联
 

2.缓冲

标准I/O库提供缓冲的目的就是尽可能减少read和write系统调用的使用次数
标准I/O提供三种类型的缓冲:
(1) 全缓冲:在填满标准I/O缓冲区后才进行实际I/O操作,磁盘上的文件通常是全缓冲,第一次I/O操作时调用malloc获得需要使用的缓冲区
(2)行缓冲:输入输出遇到换行符时,标准I/O库执行I/O操作。涉及终端时(标准输入和标准输出)通常使用行缓冲
                 标准I/O库用来收集每一行的缓冲区的长度是固定的,只要填满了缓冲区,就一定会进行I/O操作
(3)不带缓冲:标准出错流stderr通常是不带缓冲的,这使得出错信息可以尽快显示出来
setbuf  setvbuf
 
使用标准I/O的一个优点就是无需考虑缓冲以及最佳I/O长度的选择
 

3.二进制I/O

(1)读或写一个二进制数组,例如,将一个浮点数组的第2-5个元素写至一个文件
float data[];
fwrite(&data[], sizeof(data[]), , fp);

(2)读或写一个结构体

struct {
short count;
long total;
char name[NAMESIZE];
} item; fwrite(&item, sizeof(item), , fp);

4.测试I/O性能

  #include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> #define BUFSIZE 1
//#define BUFSIZE 8
//#define BUFSIZE 64
//#define BUFSIZE 256
//#define BUFSIZE 1024
//#define BUFSIZE 4096
//#define BUFSIZE 9182 int main(int argc, char* argv[])
{
char buf[BUFSIZE];
int nbytes = ;
/* unix read version */
/*
while ((nbytes = read(STDIN_FILENO, buf, BUFSIZE)) > 0) {
if (write(STDOUT_FILENO, buf, nbytes) != nbytes) {
fprintf(stderr, "write error\n");
}
}
if (nbytes< 0) {
fprintf(stderr, "read error\n");
}
*/ /* std c I/O version */
int c;
while ((c = fgetc(stdin)) != EOF) {
if (fputc(c, stdout) == EOF) {
fprintf(stderr, "fputc error\n");
}
}
if (ferror(stdin)) {
fprintf(stderr, "fgetc error\n");
} return ;
}

我们查看程序的测试文本: stat test.txt

得知:该测试文件为 259,546,640Byte, I/O块大小为 4096字节

BUFSIZE 用户CPU时间 系统CPU时间 时钟时间 系统调用数
1 30.302 555.702 588.962 259,546,640
8 3.672 71.468 75.741 32,443,330
64 0.460 9.165 9.877 4,055,417
256 0.108 2.600 3.011 1,013,854
1024 0.052 1.020 1.889 253,464
0.016 0.512 1.649 63,366
9182 0.000 0.596 1.735 31,683
fgetc fputc 7.604 0.380 8.001  

从上表可以看出:

(1) BUFSIZE直接决定了 系统调用数,所以使用unix I/O的关键在于选取最合适的缓冲区长度

(2)当BUFSIZE等于 文件 I/O块大小时,系统CPU时间出现最小值,继续增加缓冲区长度对此时间几乎没有影响

(3)fgetc fputc标准I/O自行管理缓冲区,但是其时间都大于 unix I/O最佳缓冲区时的时间值,使用标准I/O库时,系统会自动选取一个最佳I/O长度

一般依据文件的I/O块大小值,但是因为标准I/O的内部缓冲 和 unix I/O最佳缓冲区长度相等时,标准I/O库中有一个 外存文件==> FILE内部缓冲 ==> 应用缓冲,

而Unix I/O 是直接 外存文件 ==> 应用缓冲, 两者虽然系统调用数相同,但是 标准I/O多了缓冲的操作,所以效率较低

APUE 学习笔记(四) 标准I/O库的更多相关文章

  1. muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制

    目录 muduo网络库学习笔记(四) 通过eventfd实现的事件通知机制 eventfd的使用 eventfd系统函数 使用示例 EventLoop对eventfd的封装 工作时序 runInLoo ...

  2. 官网实例详解-目录和实例简介-keras学习笔记四

    官网实例详解-目录和实例简介-keras学习笔记四 2018-06-11 10:36:18 wyx100 阅读数 4193更多 分类专栏: 人工智能 python 深度学习 keras   版权声明: ...

  3. APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

    转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...

  4. APUE学习笔记3_文件IO

    APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...

  5. 零拷贝详解 Java NIO学习笔记四(零拷贝详解)

    转 https://blog.csdn.net/u013096088/article/details/79122671 Java NIO学习笔记四(零拷贝详解) 2018年01月21日 20:20:5 ...

  6. Linux学习笔记(四) vi编辑器

    一.vi 编辑器 vi 编辑器 (Visual Interface) 是所有 Unix 及 Linux 系统下标准的编辑器,相当于 Windows 系统中的记事本 它有三种模式,分别是: Comman ...

  7. go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用)

    目录 go微服务框架kratos学习笔记四(kratos warden-quickstart warden-direct方式client调用) warden direct demo-server gr ...

  8. openresty 学习笔记四:连接mysql和进行相关操作

    openresty 学习笔记四:连接mysql和进行相关操作 毕竟redis是作为缓存,供程序的快速读写,虽然reidis也可以做持久化保存,但还是需要一个做数据存储的数据库.比如首次查询数据在red ...

  9. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

随机推荐

  1. J.U.C知识点梳理

    java.util.concurrent : 提供了并发编程的解决方案 1.CAS 是java.util.concurrent.atomic包的基础 2.AQS是java.util.concurren ...

  2. python-判断alter是否存在

    from selenium import webdriver import time from selenium.webdriver.support.ui import WebDriverWait f ...

  3. iOS下的2D仿射变换机制(CGAffineTransform相关)

    仿射变换简介 仿射变换源于CoreGraphics框架,主要作用是绘制2D级别的图层,几乎所有iOS设备屏幕上的界面元素都是由CoreGraphics来负责绘制.而我们要了解的2D仿射变换是其下负责二 ...

  4. React入门教程(二)

    前言 距离上次我写 React 入门教程已经快2个月了,年头年尾总是比较忙哈,在React 入门教程(一)我大概介绍了 React 的使用和一些注意事项,这次让我们来继续学习 React 一. Rea ...

  5. Mysql中反引号和单引号的区别

    反引号,一般在ESC键的下方. 它是为了区分MYSQL的保留字与普通字符而引入的符号.举个例子:SELECT `select` FROM `test` WHERE select='字段值'在test表 ...

  6. Docker 容器的网络连接 & 容器互联

    1. Docker 容器网络基础架构 Docker0 ifconfig查看到的 docker0 是linux的虚拟网桥(OSI数据链路层) docker0 地址划分: 172.17.42.1 255. ...

  7. 【nginx】nginx.sh nginx 安装脚本

    #! /bin/shcd /usr/local/srcwget http://nginx.org/download/nginx-1.10.1.tar.gzecho 'download success' ...

  8. optimize table在优化mysql时很重要

    一个表的数据量有1000W条,那么查看这么表占据的硬盘空间时会发现,数据本身是300M,索引是200M 这个时候,删除掉500W条数据,这个时候数据本身150M,而索引还是200M左右 你删除数据时, ...

  9. HBase0.94.2-cdh4.2.0需求评估测试报告1.0之一

    hbase是bigtable的开源山寨版本.是建立的hdfs之上,提供高可靠性.高性能.列存储.可伸缩.实时读写的数据库系统.它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的r ...

  10. MMM的一周计划 准备公告

    (19.6.17——19.6.22) 目前本周还没有过去所以还会更新 第0周 目前博客更新暂定于 [题目难度颜色见洛谷] 1.绿题以上绝对更新 2.黄题可能更新 3.其他估计不会有更新 准备工作 1. ...