先来看看C标准I/O库函数是如何用系统调用实现的。

fopen(3)

调用open(2)打开指定的文件,返回一个文件描述符(就是一个int 类型的编号),分配一 个FILE 结构体, 通常里面包含了:

  • 文件fd
  • 缓冲区指针
  • 缓冲区长度
  • 当前缓冲区读取长度
  • 出错标志

返回这 个FILE 结构体的地址。

fgetc(3) 
通过传入的FILE *参数找到该文件的描述符、I/O缓冲区和当前读写位置,判断能否从I/O缓冲
区中读到下一个字符,如果能读到就直接返回该字符,否则调用read(2),把文件描述符传进
去,让内核读取该文件的数据到I/O缓冲区,然后返回下一个字符。注意,对于C标准I/O库来 说,打开的文件由FILE
*指针标识,而对于内核来说,打开的文件由文件描述符标识,文件描述符从open 系统调用获得,在使用read 、write 、close
系统调用时都需要传文件描述符。

fputc(3) 
判断该文件的I/O缓冲区是否有空间再存放一个字符,如果有空间则直接保存在I/O缓冲区中并 返回,如果I/O缓冲区已满就调用write(2) ,让内核把I/O缓冲区的内容写回文件。

fclose(3) 
如果I/O缓冲区中还有数据没写回文件,就调用write(2) 写回文件,然后调用close(2) 关闭文 件,释放FILE 结构体和I/O缓冲区。

以写文件为例,C标准I/O库函数(printf(3) 、putchar(3) 、fputs(3) )与系统调用write(2) 的关 系如下图所示。

库函数与系统调用的层次关系

open 、read 、write 、close 等系统函数称为无缓冲I/O(Unbuffered I/O)函数,因为它们位于C标 准库的I/O缓冲区的底层。用户程序在读写文件时既可以调用C标准I/O库函数,也可以直接调用 底层的Unbuffered I/O函数,那么用哪一组函数好呢?

用Unbuffered I/O函数每次读写都要进内核,调一个系统调用比调一个用户空间的函数要慢很 多,所以在用户空间开辟I/O缓冲区还是必要的,用C标准I/O库函数就比较方便,省去了自己 管理I/O缓冲区的麻烦。

用c标准I/O库函数要时刻注意I/O缓冲区和实际文件有可能不一致,在必要时需调 用fflush(3) 。

我们知道UNIX的传统是Everything is a file,I/O函数不仅用于读写常规文件,也用于读写设
备,比如终端或网络设备。在读写设备时通常是不希望有缓冲的,例如向代表网络设备的文
件写数据就是希望数据通过网络设备发送出去,而不希望只写到缓冲区里就算完事儿了,当网络设备接收到数据时应用程序也希望第一时间被通知到,所以网络编程通常直接调
用Unbuffered I/O函数。

C标准库函数是C标准的一部分,而Unbuffered
I/O函数是UNIX标准的一部分,在所有支持C语言的 平台上应该都可以用C标准库函数(除了有些平台的C编译器没有完全符合C标准之外),而只有
在UNIX平台上才能使用Unbuffered I/O函数,所以C标准I/O库函数在头文件stdio.h中声明, 而read 、write
等函数在头文件unistd.h 中声明。在支持C语言的非UNIX操作系统上,标准I/O库的
底层可能由另外一组系统函数支持,例如Windows系统的底层是Win32
API,其中读写文件的系统 函数是ReadFile 、WriteFile 。

参考: 《linux c 编程一站式学习》

C 标准IO 库函数与Unbuffered IO函数的更多相关文章

  1. 标准c库函数和linux系统函数的关系

    c库IO函数的工作流程 c库函数与系统函数的关系 虚拟地址空间 文件描述符

  2. C标准I/O库函数与Unbuffered I/O函数

    一.C标准I/O库函数.Unbuffered I/O函数 1. C标准I/O库函数是如何用系统调用的 fopen(3) 调用open(2)打开制定的文件,返回一个文件描述符(一个int类型的编号),分 ...

  3. UNIX环境高级编程——标准I/O库函数和Unbuffered I/O函数

    以写文件为例,C标准I/O库函数(printf(3) .putchar(3) .fputs(3) )与系统调用write(2) 的关 系如下图所示. 库函数与系统调用的层次关系 open .read ...

  4. nodejs选择JavaScript作为开发语言,是因为一般的开发语言的标准库都是带有IO模块的,并且通常这个 模块是阻塞性的,所以nodejs选择了没有自带IO模块的Javascript

    Javascrip本身不带IO功能,nodejs选择JavaScript作为开发语言,是因为一般的开发语言的标准库都是带有IO模块的,并且通常这个 模块是阻塞性的,所以nodejs选择了没有自带IO模 ...

  5. Python文件操作函数os.open、io.open、内置函数open之间的关系

    Python提供了多种文件操作方式,这里简单介绍os.open.io.open.内置函数open之间的关系: 一.内置函数open和io.open实际上是同一个函数,后者是前者的别名: 二.os.op ...

  6. Linux Network IO Model、Socket IO Model - select、poll、epoll

    目录 . 引言 . IO机制简介 . 阻塞式IO模型(blocking IO model) . 非阻塞式IO模型(noblocking IO model) . IO复用式IO模型(IO multipl ...

  7. Java IO系列之一:IO

    1. 概述 Java IO一般包含两个部分: 1.java.io包中堵塞型IO: 2.java.nio包中的非堵塞型IO,通常称为New IO. java.io包下,分为四大块近80个类: 1.基于字 ...

  8. 理论铺垫:阻塞IO、非阻塞IO、IO多路复用/事件驱动IO(单线程高并发原理)、异步IO

    完全来自:http://www.cnblogs.com/alex3714/articles/5876749.html 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同 ...

  9. 事件驱动模型 IO多路复用 阻塞IO与非阻塞IO select epool

    一.事件驱动 1.要理解事件驱动和程序,就需要与非事件驱动的程序进行比较.实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的.早期则存在许多非事件驱动的程序,这样的程序,在需要等待 ...

随机推荐

  1. Android数据展示之ListView

    Android应用程序中经常需要使用ListView展示数据,一个ListView通常将数据填充到布局文件中,在填充的过程中需要知道连接数据与ListView的适配器.适配器是一个连接数据和Adapt ...

  2. Android音乐播放-MediaPlayer

    当你坐公交无聊的时候,当你淹没在地铁中人潮中的时候,你是否想内心保持一份的安静呢,那么请带上耳机,打开你的音乐播放器,听一首老歌带你进入宁静的世界,音乐播放这个功能在智能手机出现之前,诺基亚时代,甚至 ...

  3. 反射 Reflect Modifier 修饰符工具类

    在查看反射相关的Class.Field .Constructor 等类时,看到他们都有这样一个方法:getModifiers():返回此类或接口以整数编码的 Java 语言修饰符.如需要知道返回的值所 ...

  4. Java基础(十四):泛型

    一.Java 泛型: Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就 ...

  5. C++11中万能的可调用类型声明std::function<...>

    在C++11中,callable object 包括传统C函数,C++成员函数,函数对象(实现了()运算符的类的实例),lambda表达式(特殊函数对象)共4种.程序设计,特别是程序库设计时,经常需要 ...

  6. connect-proxy rpm文件的安装

    1. rpm文件下载 http://rpm.pbone.net/index.php3?stat=3&search=connect-proxy&srodzaj=3 2. rpm的安装 h ...

  7. Cognos利用DMR与文本对象设计中国式报表

    场景:详细对于接触Cognos的人来说,简单的拖拉报表.交叉表这个工作大家都可以完成,下面我们就来实现一下类似下面的效果. 下面简单的说一下实现过程: 利用Framework Manager创建DMR ...

  8. Jmeter-Maven-Plugin高级应用:Configuring the jvm that the jmeter process runs in

    Configuring the jvm that the jmeter process runs in The JMeter Maven plugin will run the JMeter proc ...

  9. Java开发中所遇问题积累

    1.判断两个字符串是否相等时,如下,使用" == "无效: String name = "Jack"; if(name.equals("Jack&qu ...

  10. MongoDB和关系型数据库简单对比

    MongoDB 是一个跨平台的,面向文档的数据库,提供高性能,高可用性和可扩展性方便. MongoDB 工作在收集和文件的概念. 数据库:数据库是一个物理容器集合.每个数据库都有自己的一套文件系统上的 ...