read 与 fread 的区别的误解

来源:互联网 发布:云计算的三层架构 编辑:程序博客网 时间:2024/05/01 19:49

   http://blog.sina.com.cn/s/blog_93b45b0f01014qyb.html

    前多时间梳理了一些Linux上的编程,其实就是认识的大量的系统调用(POSIX)。这里有一个我们经常提出的问题就是fread,read的区别。(当然这两个分别代表了操作文件系统的两套不同的函数,包括open,read, write, seek 等)。我们都知道,他们的区别就是一个(read)是UNIX 中的系统调用,是类UNIX系统,提供给程序员操作文件的接口(要不然你如何操作文件?);而另外一个则是C语言提供的读取文件的函数库,自然这个函数库(ANSI)的实现是以对应的系统调用为基础的。

那么为什么C语言的函数库需要向我们提供这样的包装,而其他的系统调用(像进程、线程管理与通信等等)没有这样的包装呢?

这当然是有原因的,也就是我们常说的有缓冲读写和无缓冲读写。

 

但是,我们进一步学习了UNIX系统中,直接I/O的概念之后,对上面的了解需要更深一步了。

 

为什么要缓冲?

 

我们先不管用户态、核心态这些事情,我们先思考,读取外设上的文件为什么需要缓冲。

(我们知道,一般意义上流的概念已经被使用到了文件读写中,这个概念与缓冲的概念没有关系。)

我们使用函数向某个文件从当前流标签所在位置,读取n个字符。我们也会使用函数向文件的某个流位置写如n字符。但是,当这种写的动作小、而频繁。每次写又必须反映到硬盘上,也就是说需要频繁的操作硬盘,写一些小的更改,这是非常耗损效率。所以自然我们想到了,我们设立一个缓冲区,将那些要写入的数据先写到缓冲区中,当缓冲区满,或者其他情况发生的时候,我们在一起将他们写入到硬盘上。这样可以大大提高应用程序读写文件的速度。

 

这就是为什么需要缓冲,根本原因我认为是磁盘等外设的数据还和内存的速度相差甚远,所以我们不希望由于操作外设的原因让本来很快的内存和CPU跟着一起慢,我们想的办法:一是异步写(但这有时候不能符合应用要求),二就是缓冲读写。

 

而我们通常所理解的就是,read体系,就是那种无缓冲读写,不管是读还是写,调用这个体系的函数,会马上启动一次外设操作,读取数据或者写入数据。而fread体系则,使用了缓冲读写的方式,一定时间才调用read体系的函数。

 

上面的认识,事实上可以一定程度上说明问题的。但是,我们也太低估UNIX系统的智商了,要知道,不只是应用程序需要与外设进行交互,操作系统更是要与外设频繁的交互。(事实上应用程序是通过操作系统与外设交互的,所以就有了用户态和核心态概念)。

 

我们知道,应用程序要读写文件,一般是通过操作系统的(这样才发挥了操作系统管理系统的各项硬软件的功能)。读写的过程并不是直接将外设中的数据,直接往用户应用程序的空间传送(虽然理论上好像可以,内核还不能往用户空间写数据?但是这不符合这种隔离的思想),而是首先由内核发出外设操作,将数据传送到内核空间中(DMA技术),然后从内核传送的用户空间中。这样的好处就是能够隔离开应用程序与硬件设备的直接交流(那会导致应用软件设计的复杂都增长)。但是这也导致了我们通常说的“多拷贝”问题。

 

在操作系统内核的管理下,数据想要从一个文件到另外一个文件,需要经过:

文件1(外设)——>内核空间——>用户空间——>内核空间——文件2(外设)。

这里还是假设用户空间里面该数据没有拷贝动作,我们可以看到,中间的拷贝过程全部发生在内存中,只是分在内核与用户的区别。

 

这种样的过程其实是伤害效率的,但是如果不是对读写效率的要求过于苛刻,仍然使用这种方法。

 

事实上,read体系也有自己的缓冲机制,但是我们可以通过设置(open函数中DIRECT标志),放弃这种方式。

我们可以说,fread是在用户应用程序空间中,自己建立了一个缓冲机制,这种缓冲机制和内核read的缓冲机制并不冲突。

事实上,当我们使用read体系的时候,我们放弃了应用程序空间中的缓冲机制,但是如果不设置DIRECT标志,内核中的缓冲机制依然存在。

 

我们还有一种特殊的读写应用程序,叫着自缓冲读写,其实fread就是这样一种方式。只是它没有放弃内核的缓冲机制。但是对于复杂应用程序,例如数据库,这种对读写效率要求高的地方,他们使用了自己定义缓冲机制并且毅然放弃了内核的缓冲方式,为什么呢?因为内核缓冲方式,对缓冲数据何时应该存入到硬盘上,哪些数据应该留下来更久没有应用背景相关的信息,所以它所出来的决策,通常是盲目的。但是,如果应用程序自己设置这种缓冲,可以很大程度上弥补这一问题。

 

 

缓冲I/O绝对有它的好处,这种机制的使用不仅在用户空间中,也在内核实现时会使用。当然有时候我们为了追求某些特别的需求,会使用直接I/O方式。当然事实上,这种I/O方式与缓冲与否不是对立的。但是往往这样做了之后,缓冲就不够。我们要使用直接I/O要慎重考虑,你应用程序的需求,例如,你需要存取大块数据。这个是否“多拷贝”无疑是一个问题。其中取舍需要仔细考虑、权衡。

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信密码锁定了怎么办 电脑网易云音乐闪退怎么办 逆战耳机电流声怎么办 肠道感染一直吃药治不好怎么办 如果24小时以后还没到账该怎么办 在游戏平台充值没到账该怎么办 充值豪华黄钻没到账该怎么办 起点签到签满了怎么办 ipad锁屏声音小怎么办 扣扣邮箱文件超大了怎么办 网易邮箱图片已过期怎么办 邮箱里面的文件过期了怎么办 邮箱发的文件过期了怎么办 邮箱发送的文件过期怎么办 小米4s开不开机怎么办 小米平板关机后开不开机怎么办 公司老板跑路了社保怎么办 公司老板跑路社保怎么办 公司被公安局查封社保怎么办 小米四开不了机怎么办 小米的手机后壳裂了怎么办 公司没钱拖欠员工社保怎么办 小米note充不进去电怎么办 公司欠社保没交怎么办 公司不给转社保怎么办 小米note充电特别慢怎么办 小米小米note2充电慢怎么办 小米note充电红灯不闪烁怎么办 小米note充电红灯闪烁怎么办 小米note2突然充电慢怎么办 充电小米note2手机闪烁怎么办 小米6x上网慢怎么办 小米5数据上网慢怎么办 小米5c照相模糊怎么办 小米5充电很慢怎么办 iphone图库照片没了怎么办 我想通过微信号得到手机号怎么办 给充电宝充电慢怎么办 小米5s充不了电怎么办 百度网盘下载速度慢怎么办 负债累累没有钱没有资源怎么办