fread读取整个文件_IO FILE之fread详解

这是IO FILE系列的第二篇文章,主要写的是对于fread函数的源码分析,描述fread读取文件流的主要流程以及函数对IO FILE结构体以及结构体中的vtable的操作。流程有点小复杂,入坑需谨慎。

总体流程

第一篇文章fopen[1]的分析,讲述了系统如何为FILE结构体分配内存并将其链接进入_IO_list_all的。

这篇文章则是说在创建了文件FILE以后,fread如何实现从文件中读取数据的。在开始源码分析之前,我先把fread的流程图给贴出来,后面在分析源码的时候,可以适时的参考下流程图,增进理解:

3a2e6a4ae2b93de83b691ce3d77962b1.png

从图中可以看到,整体流程为fread调用_IO_sgetn_IO_sgetn调用vtable中的_IO_XSGETN也就是_IO_file_xsgetn_IO_file_xsgetnfread实现的核心函数。它的流程简单总结为:

1.判断fp->_IO_buf_base输入缓冲区是否为空,如果为空则调用的_IO_doallocbuf去初始化输入缓冲区。2.在分配完输入缓冲区或输入缓冲区不为空的情况下,判断输入缓冲区是否存在数据。3.如果输入缓冲区有数据则直接拷贝至用户缓冲区,如果没有或不够则调用__underflow函数执行系统调用读取数据到输入缓冲区,再拷贝到用户缓冲区。

源码分析

仍然是基于glibc2.23的源码分析,使用带符号的glibc对程序进行调试。

fread的函数原型是:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);The  function fread() reads nmemb items of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.

demo程序如下:

#includeint main(){
        char data[20];    FILE*fp=fopen("test","rb");    fread(data,1,20,fp);    return 0;}

要让程序可以运行,执行命令echo 111111>test,然后gdb加载程序,断点下在fread,开始一边看源码,一边动态跟踪流程。

程序运行起来后,可以看到断在_IO_fread函数。在开始之前我们先看下FILE结构体fp的内容,从图里可以看到此时的_IO_read_ptr_IO_buf_base等指针都还是空的,后面的分析一个很重要的步骤也是看这些指针是如何被赋值以及发挥作用的:

424332d249562f010c3c8161f9bc8d0d.png

vtable中的指针内容如下:

dd25caaa72dfe8af8905a18b54042440.png

fread实际上是_IO_fread函数,文件目录为/libio/iofread.c

_IO_size_t_IO_fread (void *buf, _IO_size_t size, _IO_size_t count, _IO_FILE *fp){
      _IO_size_t bytes_requested = size * count;  _IO_size_t bytes_read;  ...  # 调用_IO_sgetn函数  bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested);  ...  return bytes_requested == bytes_read ? count : bytes_read / size;}libc_hidden_def (_IO_fread)

_IO_fread函数调用_IO_sgetn函数,跟进去该函数:

_IO_size_t_IO_sgetn (_IO_FILE *fp, void *data, _IO_size_t n){
      /* FIXME handle 
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值