一、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个字节。