您的位置:首页 > 产品设计 > UI/UE

APUE 学习笔记(四) 标准I/O库

2014-05-06 19:53 267 查看

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[10];
fwrite(&data[2], sizeof(data[0]), 4, fp);


(2)读或写一个结构体

struct {
short count;
long  total;
char  name[NAMESIZE];
} item;

fwrite(&item, sizeof(item), 1, 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 = 0;
/* 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 0;
}


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

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

BUFSIZE用户CPU时间系统CPU时间时钟时间系统调用数
130.302555.702588.962259,546,640
83.67271.46875.74132,443,330
640.4609.1659.8774,055,417
2560.1082.6003.0111,013,854
10240.0521.0201.889253,464
40960.0160.5121.64963,366
91820.0000.5961.73531,683
fgetc fputc7.6040.3808.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多了缓冲的操作,所以效率较低
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: