标准I/O与文件I/O的区别

1.来源

参考博文

  1. 文件I/O(低级I/O)是Linux系统调用,通过系统调用来访问文件,返回一个文件描述符,可以直接对文件进行读写。需要进行内核与用户之间的切换。
  2. 标准I/O(高级I/O)是c语言的标准库,返回一个指向文件结构的指针,建立缓冲区存储文件的数据,结构中记录着文件的信息,不在内核上操作,不需要频繁切换。

2.移植性

  1. 文件I/O是Linux(Unix)的系统调用操作,移植性较差。
  2. 标准I/O是c语言标准库,大多数操作系统上都装备了c库,移植性较好。

3作用范围

  1. open返回 文件描述符,而文件描述符是Linux系统下一个重要的概念,Linux下一切设备都是以文件的形式操作,如网络套接字、硬件设备。当然包括操作普通正规文件(Regular file)。
  2. fopen是用来操作普通正规文件(Regular file)的。

4.文件IO的层次

文件IO属于低级IO,标准IO属于高级IO,简单区分高级低级的标准是:谁离内核更近就是低级。文件IO运行在内核态,标准IO运行在用户态。

5.缓冲参考博文

  1. 缓冲文件系统
    缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用(每打开一个文件,就会新建一个缓冲区);当执行读文件的操作时,从磁盘将文件数据先读入内存“缓冲区”,装满后再从内存“缓冲区”一次读出需要的数据。执行写文件先将数据写入内存“缓冲区”,待内存“缓冲区”填满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快,效率高。 一般来说,文件的“缓冲区”大小随机器而定。
  2. 非缓冲文件系统
    缓冲文件系统是借助文件结构指针来对文件进行管理,通过文件指针对来对文件进行访问,既可以写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统的输入输出,它不设为念结构指针,只能读写二进制文件,但效率高、速度快。

实际上不管时文件IO还是标准IO都是先写到内核设立的缓冲区上,满了之后在写入文件(磁盘)。标准IO则多一个缓冲区,等缓冲区满了在写入内核缓冲区,减少 系统调用的次数,增加效率。

如果我们直接用非缓存I/O对内核的缓冲区进行读写,会产生许多管理不善而造成的麻烦(如一次性写入过多,或多次系统调用导致的效率低下)。
标准(带缓存的)I/O为我们解决了这些问题,它处理很多细节,如缓冲区分配,以优化长度执行I/O等,更便于我们使用。

标准I/O对每个I/O流自动进行缓存管理(标准I/O函数通常调用malloc来分配缓存)。它提供了三种类型的缓存:
1) 全缓存。当填满标准I/O缓存后才执行I/O操作。磁盘上的文件通常是全缓存的。
2) 行缓存。当输入输出遇到新行符或缓存满时,才由标准I/O库执行实际I/O操作。stdin、stdout通常是行缓存的。
3) 无缓存。相当于read、write了。stderr通常是无缓存的,因为它必须尽快输出。

通过文件I/O读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销,标准I/O可以看成是在文件I/O的基础上封装了缓冲机制。先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数。

文件I/O中用文件描述符表现一个打开的文件,可以访问不同类型的文件如普通文件、设备文件和管道文件等。而标准I/O中用FILE(流)表示一个打开的文件,通常只用来访问普通文件。

系统调用

在这里插入图片描述

POSIX:Portable Operating System Interface 可移植操作系统接口
ANSI:American National Standrads Institute 美国国家标准学会

1、系统调用

操作系统负责管理和分配所有的计算机资源。为了更好地服务于应用程序,操作系统提供了一组特殊接口——系统调用。通过这组接口用户程序可以使用操作系统内核提供的各种功能。例如分配内存、创建进程、实现进程之间的通信等。

为什么不允许程序直接访问计算机资源?答案是不安全。单片机开发中,由于不需要操作系统,所以开发人员可以编写代码直接访问硬件。而在32位嵌入式系统中通常都要运行操作系统,所以开发人员可以编写代码直接访问硬件。而在32位嵌入式系统中通常都要运行操作系统,程序访问资源的方式都发生了改变。操作系统基本上都支持多任务,即同时可以运行多个程序。如果允许程序直接访问系统资源,肯定会带来很多问题。因此,所有软硬件资源的管理和分配都有操作系统负责。程序要获取资源(如分配内存,读写串口)必须由操作系统来完成,即用户程序向操作系统发出服务请求,操作系统收到请求后执行相关的代码来处理。

用户程序向操作系统提出请求的接口就是系统调用。所有的操作系统都会提供系统调用接口,只不过不同的操作系统提供的系统调用接口各不相同。Linux 系统调用接口非常精简,它继承了Unix 系统调用中最基本的和最有用的部分。这些系统调用按照功能大致可分为进程控制、进程间通信、文件系统控制、存储管理、网络管理、套接字控制、用户管理等几类。

2、库函数

库函数可以说是对系统调用的一种封装,因为系统调用是面对的是操作系统,系统包括Linux、Windows等,如果直接系统调用,会 影响程序的移植性 ,所以这里使用了库函数,比如说C库,这样只要系统中安装了C库,就都可以使用这些函数,比如printf() scanf()等,C库相当于对系统函数进行了翻译,使我们的APP可以调用这些函数

3、用户编程接口API

前面提到利用系统调用接口程序可以访问各种资源,但在实际开发中程序并不直接使用系统调用接口,而是使用用户编程接口(API) 。为什么不直接使用系统调用接口呢?

原因如下:

1)系统调用接口功能非常简单,无法满足程序的需求。

2)不同操作系统的系统调用接口不兼容,程序移植时工作量大。

用户编程接口通俗的解释就是各种库(最重要的就是C库)中的函数。为了提高开发效率,C库中实现了很多函数。这些函数实现了常用的功能,供程序员调用。这样一来,程序员不需要自己编写这些代码,直接调用库函数就可以实现基本功能,提高了代码的复用率 。使用用户编程接口还有一个好处:程序具有良好的可移植性 。几乎所有的操作系统上都实现了C库,所以程序通常只需要重新编译一下就可以在其他操作系统下运行。

用户编程接口(API)在实现时,通常都要依赖系统调用接口。例如,创建进程的API函数fork()对应于内核空间的sys_fork()系统调用。很多API函数西亚我哦通过多个系统调用来完成其功能。还有一些API函数不要调用任何系统调用。

在Linux 中用户编程接口(API)遵循了在Unix中最流行的应用编程界面标准——POSIX标准。POSIX标准是由IEEE和ISO/IEC共同开发的标准系统。该标准基于当时想用的Unix 实践和经验,描述了操作系统的系统调用编程接口(实际上就是API),用于保证应用程序可以在源代码一级商多种操作系统上运行。这些系统调用编程接口主要是通过C库(libc )实现的。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值