免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
论坛 程序设计 C/C++ fread()
最近访问板块 发新帖
楼主: chenzhanyiczy

fread() [复制链接]

论坛徽章:
0
发表于 2010-02-24 09:43 |显示全部楼层
先要对read和fread的应用场合有些认识.
read是通用的读,可以读各种类型的file.
File is of type c:

              b      block (buffered) special

              c      character (unbuffered) special

              d      directory

              p      named pipe (FIFO)

              f      regular file

              l      symbolic  link;

              s      socket

              D      door (Solaris)
而fread使用的场合通常就是上面的regular file(这里也没有说绝对),在系统的角度看就是在块设备上的可随机读写的某文件系统文件.进而我们可以简单的认为fread就是读磁盘(包括flash/sd卡之类的)上的逻辑块,而这最终要读物理块.通常认为读同一片同样大小的数据,多次读物理块比一次读要开销大,因此系统的文件系统通常会进行预读.涉及buffer的东西通常有命中的概念,如果读的东西很随机并稀疏,那么命中buffer的命中率就很低,效率也就会很低.从统计的规律来看,局部读概率很高,设置预读进行缓冲在多数情况下有效,这也大概是其存在的缓冲的原因.That is it.

论坛徽章:
0
发表于 2010-02-24 14:00 |显示全部楼层
To JohnBull:
To JohnBull:
那也得看怎么用吧?如果是一个一个字节的写,比如fputc,这样多次调用效率确实会有影响,但是谁会用fread或者fwrite一个一个字节读写呢?绝大多数情况下,用到这两个函数的时候都是一片一片的内存操作。内核的缓冲没有想象的那么慢,一片一片的读写效率不会差。
另外,如果是用fwrite写日志,一般是组好日志字符串,调用一下写函数,如果是用fwrite还得跟一个fflush,有必要么?
w_anthony 发表于 2010-02-24 09:22



sorry, 我的评语没有显示完全。

1 参见3楼的意见

2 “一片”究竟是多大?你认为多大一片数据的读写可以让用户态buffer失去意义?难道你先要

  1. if (len >= 一片) {
  2.     write();
  3. } else {
  4.     fwrite();
  5. }
复制代码
不成???

3 日志那个情况是你自己对库函数的误用,而不是库函数“多此一举”。

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
发表于 2010-02-24 14:20 |显示全部楼层
sorry, 我的评语没有显示完全。

1 参见3楼的意见

2 “一片”究竟是多大?你认为多大一片数据的 ...
JohnBull 发表于 2010-02-24 14:00



如果是要一个一个字节的写,那么fputc之类的是会快一点,如果有一个一个字节与一片一片字节的混合写入,那还得是用fwrite,总不能一部分库缓冲,一部分不缓冲写入吧?同理write和fwrite也不适合混合着用,否则用write前就必须fflush。
对linux进内核的方式没研究,windows进内核从XP开始就是sysenter指令(以前是int 2e),离开是sysexit指令,只是几个寄存器简单交换了一下就完成了转换,速度是相当的快。对于一片是多少,我不好下定论,看应用决定。
最后可能是我误用了库函数了,那么请问写日志该怎么弄比较好?

论坛徽章:
0
发表于 2010-02-24 15:10 |显示全部楼层
如果是要一个一个字节的写,那么fputc之类的是会快一点,如果有一个一个字节与一片一片字节的混合写入 ...
w_anthony 发表于 2010-02-24 14:20



1 如果你不能在编码阶段就预测写入数量,可能多可能少,你该怎么办?用write还是fwrite?
2 系统调用的开销不是几条机器指令,不了解内核就去了解一下内核,看不见windows的就去看Linux的
3 日志处理的常规手段: syslog(3)/fprintf(stderr, )/setvbuf()设置流缓冲模式/...
4 标准IO库的关键在于“标准”二字!意味着可移植性!别动不动就断言什么“多此一举”!

论坛徽章:
0
发表于 2010-02-24 15:21 |显示全部楼层
没缓冲效率会低吧

论坛徽章:
0
发表于 2010-02-24 16:41 |显示全部楼层
版主已经说得很明白了 如果你还是有疑惑 可以用 对比 strace 调试下

比如
#include <stdio.h>
#include <assert.h>
#include <string.h>

char * fname = "hello.txt";
char * poem = " Poem is a song by nu metal band \
                           Taproot and the lead single from  \
                           their second major label album, Welcome. \
                           It was released in 2002 and met with the \
                           highest success of any Taproot single, \
                           reaching #5 on the Billboard Mainstream Rock Tracks. ...\
                           " ;

int main() {

    FILE * file_ptr = fopen( fname,"w+") ;
        assert(file_ptr) ;
   
        fwrite(poem, 1,strlen(poem), file_ptr);
        fclose(file_ptr);
    return 0 ;
}

strace -c a.out

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
   nan    0.000000           0         1           read
   nan    0.000000           0         1           write
   nan    0.000000           0         3           open
   nan    0.000000           0         3           close
   nan    0.000000           0         1           execve
   nan    0.000000           0         3         3 access
   nan    0.000000           0         3           brk
   nan    0.000000           0         2           munmap
   nan    0.000000           0         1           mprotect
   nan    0.000000           0         7           mmap2
   nan    0.000000           0         3           fstat64
   nan    0.000000           0         1           set_thread_area
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                    29         3 total

论坛徽章:
0
发表于 2010-02-24 17:07 |显示全部楼层
标准I/O以及通常意义上的用户缓冲,在以下任何条件满足时都是有意义的:
  你需要发起许多系统调用,并且你希望通过合并许多调用来最小化开销。
  性能至关重要,并且你希望确保所有 I/O都以块边界对齐块大小进行。
  你的访问方式基于字符、或者基于行,并且你希望调用接口尽量简单,而不发起无关额外的系统调用。
  你更喜欢高级的接口而不是低级的 Linux系统调用。

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
发表于 2010-02-24 19:46 |显示全部楼层
1 如果你不能在编码阶段就预测写入数量,可能多可能少,你该怎么办?用write还是fwrite?
2 系统调用 ...
JohnBull 发表于 2010-02-24 15:10


我觉得你可能误解我的意思了。我最早的一楼是先说顶“操作系统的缓冲有平台依赖性,例如嵌入式系统,限于内存,操作系统层不提供缓冲也不稀奇”,如果你用移植性去做文章的话,我绝对支持使用FILE*相关的一系列操作。
1、在编码阶段无法决定写入量是一个还是一片的应用我似乎是没有遇到,如果说我“断言”多此一举,你说得对,我武断了。至少fwrite、fputc混合用,还是有用处的。
2、windows的ring0和ring3切换挺快的,用SOFTICE可以跟踪调试,进ring0后也就是根据调用号分发到指定函数需要耗费掉一些额外的时间,进函数后也就是内核缓冲过程了。
3、关掉FILE*缓冲,那fputc、fwrite与write有区别么?
4、说到移植性,我支持你的观点,用FILE*。另外我看到VC的C库里面有一套模拟read/write的函数,不知道这两个是不是也是C标准库里面的。

论坛徽章:
0
发表于 2010-02-24 20:01 |显示全部楼层
2、windows的ring0和ring3切换挺快的


”挺快的“是相对什么来说?

ring0到ring3切换一次需要多少时钟周期?普通应用层函数调用需要多少时钟周期?相差多少倍?

read()读一个字节,循环1千万次,需要多少时间?fread()读一个字节,循环1千万次,需要多少时间?相差多少倍?

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
发表于 2010-02-24 21:25 |显示全部楼层
回复 19# drangon

一字节必定是fread完胜,前面我赞同过。
测试了一下,fread和fwrite确实很有必要,我错了,高估了内核缓冲。
windows上FILE*默认缓冲区是4096,直接调用API读写文件的“一片”需要达到2048个字节(fread和ReadFile一次读2048,总共5000次),两者消耗时间才互有胜负。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2019中国系统架构师大会

【数字转型 架构演进】SACC2019中国系统架构师大会,8.5折限时优惠重磅来袭!
2019年10月31日~11月2日第11届中国系统架构师大会(SACC2019)将在北京隆重召开。四大主线并行的演讲模式,1个主会场、20个技术专场、超千人参与的会议规模,100+来自互联网、金融、制造业、电商等领域的嘉宾阵容,将为广大参会者提供一场最具价值的技术交流盛会。

限时8.5折扣期:2019年9月30日前


----------------------------------------

大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP