一、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個字節。