Linux标准I/O概述
文章目录
1.0 标准I/O 的由来
标准IO是指ANSI C(ANSI C是美国国家标准协会(ANSI)对C语言发布的标准)中定义的用于I/O操作的一系列函数。
只要操作系统中安装了C库,标准I/O函数就可以调用,换句话说,如果程序中使用的是标准I/O函数,那么源代码不需要修改就可以在其它操作系统下编译运行,具有更好的可移植性
在执行系统调用时,Linux必须从用户态切换到内核态,处理相应的请求,然后再返回到用户态。如果频繁执行必定增加系统开销,为避免这种情况,标准I/O使用时在用户空间创建缓冲区,读写实先操作缓冲区,再通过系统调用访问世纪的文件,而减少系统调用的次数。
1.2 流的含义
标准I/O的核心对象就是流。那流到底是什么呢?
当使用标准I/O打开一个文件时,就会创建一个FILE结构体,这个结构体用来描述改文件(可以理解为创建一个FILE结构体和实际打开的文件进行关联起来),我们把这个FILE结构体就称为流,标准I/O函数都基于流进行所有的操作。
1.3 标准I/O的缓冲机制
在前面我们提到了标准I./O是有缓冲机制的,缓冲区创建于用户空间,那么缓冲的具体类型有哪些呢?
其实,标准I/O中流的缓冲类型有3种:
1、全缓冲: 当填满标准I/O缓冲区后再进行实际的I/O操作。
对于存放在磁盘上的普通文件,标准I/O打开的默认就是全缓冲。当缓冲区已满或者执行FULSH操作室才会进行磁盘操作。
2、行缓冲:当在输入和输出中遇到换行符时执行I/O操作。
标准输入流和输出流就是使用行缓冲,想想printf();
的格式,就是遇到\n
后进行输出,行缓冲。
3、无缓冲: 不对I/O操作进行缓冲。
即对流的读写时会立刻操作实际的文件。标准出错流是不带缓冲的,理论上所有出错输出都不应该是缓冲的,因为出错就应该立刻输出。
1.4 标准I/O编程
本节只介绍最常用的函数。本就所讨论的I/O操作都是基于流的,它包含ANSI C的标准。
首先扔一个问题,想想 open() 与 fopen()的区别?
1.4.1 流的打开
使用标准I/O打开的函数有fopen(),fdopen(),freopen()。它们可以用不同的模式打开文件,每一个都返回一个指向FILE的指针。 此后,对文件的读写都通过这个FILE指针来进行。
fopen():可以指定打开文件的路径和模式;
fdopen():可以指定打开文件的描述符和模式;
freopen():可以指定打开的文件和模式,还可以指定特定的 I/O 流;
注意:给环境变量赋值需要用 export
, 而不是直接path = "********"
有些人可能会疑惑 “b”
是干嘛的,其实在每个选项中加入 b
字符是用来告诉函数库打开的文件是二进制文件,不是纯文本文件,不过在linux系统中会忽略该符号。
注意: 当用户进程运行时,系统会自动打开 3 个流: 标准输入流stdin;标准输出流stdout;标准错误流 stderr。
标准输入流stdin:用来从标准输入设备(默认键盘)中读取输入内容;
标准输出流stdout:用来从标准输出设备(默认当前终端)中输出内容;
标准错误流 stderr:用来向标准错误设备(默认当前终端)中输出错误信息;
1.4.2 流的关闭
关闭流的函数为 fclose()
;该函数将流的缓冲区的数据全部写入文件中,并释放相关资源。
注意:程序结束时,会自动关闭所有的打开的流
1.4.3 错误信息
标准 I/O 函数执行时如果出现错误,会把错误码保存在全局变量 errno
中,程序员可以打印错误信息,处理错误的相关函数:1. perror(); 2. strerror()
perror():
其实,perror()
函数的使用还是比较简单的,在之前的错误信息输出中很多同学采用的是标记性输出,printf("************");
这种方式,这样可以利用输出的信息来断点在某个区间,但无法获取准确的错误信息,采用perror()
可以得到详细的错误原因。
来,咱不止说,拿个例子试试看。
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp; //指定流指针