fread带缓冲测试与验证

本文探讨了fread操作FILE结构的过程,指出即使读取少量数据,fread也会填充缓存区4096字节。通过使用strace工具,观察到在读取1M文件时,fread调用次数远大于read系统调用次数,揭示了fread内部的缓冲机制提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、FILE结构

fread操作的是FILE结构,FILE结构中包含了一个缓存buf的定义:

typedef struct _IO_FILE FILE;

 

struct _IO_FILE

struct _IO_FILE {
  int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* Start of putback+get area. */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr;  /* Current put pointer. */
  char* _IO_write_end;  /* End of put area. */
  char* _IO_buf_base;   /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */
  struct _IO_marker *_markers;
  struct _IO_FILE *_chain;

  int _fileno;
#if 0
  int _blksize;
#else
  int _flags2;
#endif
  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */

#define __HAVE_COLUMN /* temporary */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];
  /*  char* _save_gptr;  char* _save_egptr; */
  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE

};

二、打印_IO_FILE buf中的数据

fread.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

void init()
{
	int fd = open("1.txt", O_RDWR | O_CREAT, 0644);
	int j;
	for(j=0; j<4096; j++)
	{
		write(fd,"1",1);
	}
	for(j=0; j<4096; j++)
	{
		write(fd,"2",1);
	}
	close(fd);
}



int main()
{
	init();
	FILE *fp = fopen("1.txt", "rb");
	char buf[10];
	fread(buf, 1, 1, fp);
	printf("buf is %s \n", buf);
	printf("io_buf is %s \n",fp -> _IO_buf_base);
    fclose(fp);
}

 编译运行如下:

 可以看到,fread哪怕只读取1字节的内容,FILE结构中的缓存区也被填充了4096字节的文件内容。

三、测试fread调用系统调用read的次数

使用工具 strace或gdb

测试用1M大小的文件1.txt

fread.c:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main()
{
	int j = 0;
        char filebuf[10] = {0};
        FILE *fp = fopen("1.txt", "rb");

        if (fp == NULL)
        {
                printf("fopen error:%d:%s\n", errno, strerror(errno));
                return -1;
        }


        while (0 != fread(filebuf, 1, 1, fp))
        {
                j++;
        }

	printf("j=%d\n", j);
        return 0;
}

编译:

gcc -o debug fread.c

 

使用strace工具可以查看调用系统调用的次数: 

strace -c ./debug

可以看到,fread被调用了1024000次,而read系统调用只被调用了252次,而fread中的read系统调用为250次,每次读取4096个字节。

参考:https://blog.csdn.net/lstok2009/article/details/49765563

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值