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. Bootstrap历练实例:动画的进度条

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  2. cocos2dx 通过jni调用安卓底层方法

    cocos2dx通过封装JniHelper类来调用安卓api底层函数,该文件在cocos/platform/android/jni/JniHelper.h,使用方法如下: 打开eclipse,导入co ...

  3. 洛谷 P2735 电网

    https://www.luogu.org/problemnew/show/P2735 定理什么的最讨厌了,匹克定理?不会,也不想学. 粉色的为电网,将图中的电网我们将他构造一个矩形,然后蓝色和绿色的 ...

  4. Bzoj 近期题目一句话题解

    目录 Bzoj 近期题目题解 1000: A+B Problem (模拟) 1008: [HNOI2008]越狱 (容斥) 1012: [JSOI2008]最大数maxnumber (线段树) 103 ...

  5. node中的定时任务

    node-schedule每次都是通过新建一个scheduleJob对象来执行具体方法. 时间数值按下表表示 * * * * * * ┬ ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ | │ │ │ │ │ ...

  6. Ubuntu 开机启动不执行

    解决方案: 1.将/etc/rc.local的命令改成更加兼容的模式,将"#!/bin/sh"改为"#!/bin/bash" 2.将/bin/sh重新链接到/b ...

  7. php读取不到https的域名

    因测试环境php遇到无法正常读取到https的域名,但是域名配置了ssl证书,故做如下排查. php测试代码如下 $config['base_url'] = ''; #开启调试模式 #echo &qu ...

  8. 为什么要用 ORM? 和 JDBC 有何不一样?

    orm是一种思想,就是把object转变成数据库中的记录,或者把数据库中的记录转变objecdt,我们可以用jdbc来实现这种思想,其实,如果我们的项目是严格按照oop方式编写的话,我们的jdbc程序 ...

  9. python多进程并发进程池Pool

    简介: python中的多进程主要使用到 multiprocessing 这个库.低版本python这个库在使用 multiprocessing.Manager().Queue时会出问题,建议大家升级 ...

  10. Python9-hashilib模块-day28(大年初三)

    __getitem__\__setitem__\__delitem__ class Foo: def __init__(self,name,age,sex): self.name = name sel ...