标准缓冲I/0及其可能遇到的错误

在文件I/O中所有函数都是针对文件描述符的,对于标准I/O库,他们的操作则是围绕流进行的。当用标准I/O库打开或创

建一个文件时,我们使一个流与一个文件相关联。

当打开一个流时,标准I/O函数fopen返回一个指向FILE对象的指针。该对象通常是一个结构,它包含了标准I/O库为管理

该流所需要的所有信息,包括:用于实际I/O的文件描述符、指向用于该流缓冲区的指针、缓冲区的长度、当前在缓冲区中的

字符数以及出错标志等等。

在文件I/O中已经介绍标准I/O是提供缓冲区的。标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。标

准I/O库处理很多细节,例如缓冲区分配,以优化长度执行I/O等。

标准I/O提供了三种类型的缓冲:

1)全缓冲。这种情况下,在填满标准I/O缓冲区后才进行实际I/O操作。对于驻留在磁盘上的文件通常是由标准I/O库实施全

缓冲的。在一个流上执行第一次I/O操作时,相关标准I/O函数通常调用malloc获得需使用的缓冲区。

2)行缓冲。在这种情况下,当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符(标

准I/O fputc函数),但只有在写了一行之后才进行实际I/O操作。当流涉及一个终端时(例如标准输入和标准输出),通常使

用行缓冲。

对于行缓冲有两个限制。第一,因为标准I/O库用来收集每一行的缓冲区的长度是固定的、所以只要填满了缓冲区,那么即

使还没有写一个换行符,也进行I/O操作。第二,任何时候只要通过标准I/O库要求从(a)一个不带缓冲的流,或者(b)一

个行缓冲的流(它要求从内核得到数据)得到输入数据,那么就会造成冲洗所有行缓冲输出流。

3)不带缓冲。标准I/O库不对字符进行缓冲存储。例如,如果用标准I/O函数fputs写15个字符到不带缓冲的流中,则该函数

很可能用上面讲述的write系统调用函数将这些字符立即写至关联的打开的文件上。

对任何一个给定的流,我们可以通过以下两个函数更改缓冲类型。

[cpp] view
plain
copy

  1. #include <stdio.h>
  2. void setbuf(FILE* restrict fp, char* restrict buf);
  3. int setvbuf(FILE* restrict fp, char* restrict buf, int mode, size_t size); //如果成功返回0,出错则返回非0.

可以使用setbuf函数打开或关闭缓冲机制,为了带缓冲进行IO,参数buf必须制定一个长度为BUFSIZ的缓冲区(这就是为什么

没有在setbuf函数的参数中指定buf的长度),通常在此之后该流就是全缓冲的,但是如果该流与一个终端相关,那么某些系统也可

以将其设置为行缓冲。为了关闭缓冲,将buf设置为NULL。

使用setbuf,可以精确地指定所需的缓冲类型。mode的取值及其代表的含义如下:

_IOFBF 全部缓冲

_IOLBF 行缓冲

_IONBF 不缓冲

注意:

如果指定一个不带缓冲的流,则忽略buf和size参数。

如果指定全缓冲和行缓冲,则buf和size可选择地指定一个缓冲区及其长度。

如果该流是带缓冲的,而buff是NULL,则标准IO库将自动地为该流分配适当长度的缓冲区(长度为BUFSIZ指定的值)。

当标准I/O函数遇到fork函数(多进程)时可能会因为其缓冲问题得到不同的结果

看下面的代码:

在fork函数之前,我们执行一次write函数和printf(“before fork”)。按道理,我们的结果应该只会得到一次输出。

但是运行的结果却是如下:

从结果中我们看到 before fork 执行了两次。这是为什么呢?

这是由于缓冲区的缘故.write函数时不带缓冲区的,所以在调用write函数之后会立刻执行I/O操作,将结果输出到标准输出上。

然而printf函数(标准I/O函数)是带缓冲的,在此处是行缓冲(交互式程序中是行缓冲),当执行完printf("before fork")函数之后,系统会将结果存放在缓冲区中(因为没有遇到换行,同时也没有超过行缓冲的大小)。接下来执行fork函数之后,子进程会将上面的缓冲区的内容也复制到自己的缓冲区中,所以在父进程和子进程的缓冲区中都存在。在程序退出时,系统会将缓冲区的内容刷新到标准输出上。

时间: 2024-10-10 10:28:35

标准缓冲I/0及其可能遇到的错误的相关文章

请求部署在 IIS7.5 上的 REST 服务的 Put/Post/Delete 操作发生 HTTP Error 405.0 - Method Not Allowed 错误之解决

背景 请求部署在 IIS7.5 上的 REST 服务的 Put/POST/DELETE 操作发生 HTTP Error 405.0 - Method Not Allowed 错误. Issue 解决 在 WebAPI 应用的 Web.config 中加入如下设置: <system.webServer> <modules> <remove name="WebDAVModule" /> </modules> <handlers>

kali 2.0 U盘安装错误Your installation cd-rom couldn&#39;t be mounted

1.kali 2.0前天(2015.08.11)发布了.果断下载下来换掉本机的1.0版本. 2.用U盘安装的过程中,出现cd-rom无法挂载.提示错误Your installation CD-ROM couldn't be mounted. 3.在谷歌搜索后,参考国外的http://serverfault.com/questions/685302/unattended-installation-of-ubuntu-from-usb-drive-not-mounted-correctly 4.经过

oracle11g 数据库导出报“ EXP-00003: 未找到段 (0,0) 的存储定义”错误的解决方案

导出oracle11.2.0.2的服务器的数据时,报"EXP-00003: 未找到段 (0,0) 的存储定义"错误.初步分析是由于数据表是空表导致该问题. Oracle 11G在用EXPORT导出时,空表不能导出 11GR2中有个新特性,当表无数据时,不分配segment,以节省空间 解决方法:一. insert一行,再rollback就产生segment了. 该方法是在在空表中插入数据,再删除,则产生segment.导出时则可导出空表.二. 设置deferred_segment_cr

第二次实验判断成绩等级。 给定一百分制成绩,要求输出成绩的等级。90以上为A,80-89为B,70-79为C,60-69为D,60分以下为E,输入大于100或小于0时输出“输入数据错误”。 分别用if和用switch语句实现判断成绩等级。 给定一百分制成绩,要求输出成绩的等级。90以上为A,80-89为B,70-79为C,60-69为D,60分以下为E,输入大于100或小于0时输出“输入数据错误”

一:实验内容:1:判断成绩等级. 给定一百分制成绩,要求输出成绩的等级.90以上为A,80-89为B,70-79为C,60-69为D,60分以下为E,输入大于100或小于0时输出“输入数据错误”. 分别用if和用switch语句实现 #include <stdio.h> int main() { int grade; scanf("%d",&grade); if(grade>100||grade<0) { printf("数据错误")

64位操作系统下用Microsoft.Jet.OLEDB.4.0出现未注册错误

在WIN7 64位下用Microsoft.Jet.OLEDB.4.0方法访问数据库Access,出现未注册错误 如果是要建立64位的应用程序 1.Microsoft Access Database Engine 2010 Redistributable http://www.microsoft.com/downloads/zh-cn/details.aspx?FamilyID=C06B8369-60DD-4B64-A44B-84B371EDE16D 2.原来连接:Provider=Microso

DS-5/RVDS4.0出现变量初始化错误

最近调试的时候老是出现各种错误,一般都是内存错误,我无意间发现所有的全局变量出现问题,就是声明全局变量后,赋值的初值出现错误. 初值明明是0x12345674,最后变为了0xBA141234,出现了移位现象 测试代码 //内存测试,防止出现内存异常,主要表现为全局变量初始化有问题 #define MEM_TEST 0x12345678 u32 MemTest = MEM_TEST; _init_alloc(0x56000000, 0x60000000-8); //初始化堆的范围 pJpegBuf

Unsupported major.minor version 51.0(JDK版本错误)

Unsupported major.minor version 51.0  at java.lang.ClassLoader.defineClass1(Native Method)  at java.lang.ClassLoader.defineClassCond(Unknown Source)  at java.lang.ClassLoader.defineClass(Unknown Source)  at java.security.SecureClassLoader.defineClass

Thrift-0.10.0 CenOS 7 编译错误 error: expected &#39;)&#39; before &#39;PRIu32&#39;

Thrift-0.10.0 CenOS 7 编译错误 error: expected ')' before 'PRIu32' 在编译Thrift的时候,无论是Apache官网tar包,还是Github镜像,都会出现各种错误,其中一个比较头疼的就是标题描述的编译错误,经过捣鼓,终于妥协性的搞定了. make时的错误描述: src/thrift/server/TNonblockingServer.cpp: In member function 'void apache::thrift::server

iOS平台下闪退原因汇总(一):&quot;Ran out of trampolines of type 0/1/2&quot; 运行时间错误

"Ran out of trampolines of type 0/1/2" 运行时间错误通常出现在使用大量递归泛型时.要看到这个错误需要连接着设备直接将项目build到设备里运行调试才能看到,您可以暗示 AOT 编译器分配更多type 0.type 1 或 type 2 trampolines.此外,AOT 编译器命令行选项可以在播放器设置 (Player Settings)的其他设置 (Other Setings) 部分指定.对于 type 1 trampolines,指定 nrg