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

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时间 时钟时间 系统调用数
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
4096 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时间出现最小值,继续增长缓冲区长度对此时间几乎没有影响spa

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

通常依据文件的I/O块大小值,可是由于标准I/O的内部缓冲 和 unix I/O最佳缓冲区长度相等时,标准I/O库中有一个 外存文件==> FILE内部缓冲 ==> 应用缓冲,指针

而Unix I/O 是直接 外存文件 ==> 应用缓冲, 二者虽然系统调用数相同,可是 标准I/O多了缓冲的操做,因此效率较低code

相关文章
相关标签/搜索