UNIX标准I/O的奇奇怪怪的缓冲

“内核中设有缓冲区高速缓存或页面高速缓存,将数据写入文件时,内核先将该数据复制到其中一个缓冲区,如果该缓冲区未满,并不将其排入输出队列,而是等待其写满或当内核需要重用该缓冲区以便存放其他磁盘块数据时,再将该缓冲排入输出队列,等待其到达队首时,才进行实际的I/O操作。这种输出方式称为延迟写。”

                                                                                                                                                                                                                                                 ——《UNIX环境高级编程》61页

这里的缓冲区是内核中的,无论使用标准I/O还是文件I/O,都会存在,并非标准I/O库提供的缓冲。

“标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。”

                                                                                                                                                                                                                                                ——《UNIX环境高级编程》110页

这句话中清楚表明了提供缓冲的作用,那么提供的这个缓冲就应该的确是减少了read和write的次数(好像是废话)。但是想了想不是很理解,对于write操作比较好理解,就是冲洗(flush)了,书上也说了,“冲洗(flush)说明标准I/O缓冲区的写操作”(《UNIX环境高级编程》110页),就是只有写操作才有这么一个东西,标准I/O就可以让写操作先只是写到自己提供的缓存中,等到满足了flush的条件(比如缓冲区满了,或者行缓冲遇到回车),再调用一次write写到内核缓冲区,后面就是延迟写的问题了,不用管它。

问题是对于读操作来说,所谓的使用缓存减少read操作究竟是怎么回事?

可以看到的说法是,每次进行读操作时,会用read一次多读一些内容到缓存,然后使用标准I/O读时,每次都先从缓存读,缓存内容读完才再次调用read。

我想不明白的是到底什么时候会从缓存读,APUE上110页,在介绍三种类型的缓存时说,全缓存“这种情况,在填满标准I/O缓冲区后才进行实际I/O操作”,而行缓冲则是“当在输入和输出中遇到换行符时,标准I/O库执行I/O操作”,也就是实际的读写操作是发生在缓冲区满足了某个条件时,是否可以理解为(针对read),第一次调用标准I/O的读操作时,首先会通过read从内核获得比请求的多的数据,这样的行为会在满足某个条件时停止,然后进行实际的读,将缓存中的部分内容读到用户指定的位置(变量,buf缓存)。

使用fgets函数时,脑抽做了个实验,对APUE上118页的程序清单5-2做了一点小修改,想观察一下程序行为,修改后代码如下,我指定了标准输入使用的缓存和提供给fgets的buf缓存是同一个

运行后测试的几个输入输出如下

下面两个图是一次输入的,第一次回车后为

再敲一次回车后为

abcd的输出个人理解是因为每次先将前5个字符读入缓冲区(buf)中,这时因为缓冲满了因此将前4个字符读入fgets中指定的参数buf中,并在最后加上null,这时就将原本的(应该在标准输入缓冲中的)第5个字符覆盖了(第一个例子中是回车符,第二个例子中是e)。但是不明白的是为何后两个例子中,后面的内容会反复出现(f和回车),还有就是为何第二个例子最后的回车会一起输出到屏幕,而第三个例子中的f和回车要第二次敲回车再显示?

MD,思路是乱的,写的东西也是乱的~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值