Linux标准IO(一)-基础知识详解

1.标准I/O库简介

所谓标准 I/O 库则是标准 C 库中用于文件 I/O 操作(譬如读文件、写文件等)相关的一系列库函数的集合,通常标准 I/O 库函数相关的函数定义都在头文件<stdio.h>中,所以我们需要在程序源码中包含<stdio.h>头文件。

标准 I/O 库函数是构建于文件 I/O(open()、read()、write()、lseek()、close()等)这些系统调用之上的,譬如标准 I/O 库函数 fopen()就利用系统调用 open()来执行打开文件的操作、fread()利用系统调用 read()来执行读文件操作、fwrite()则利用系统调用 write()来执行写文件操作等等。

那既然如此,为何还需要设计标准 I/O 库?直接使用文件 I/O 系统调用不是更好吗?事实上,并非如此,在上一章中我们也提到过,设计库函数是为了提供比底层系统调用更为方便、好用的调用接口,虽然标准 I/O 构建于文件 I/O 之上,但标准 I/O 却有它自己的优势,标准 I/O 和文件 I/O 的区别如下:

  • 虽然标准 I/O 和文件 I/O 都是 C 语言函数,但是标准 I/O 是标准 C 库函数,而文件 I/O 则是 Linux系统调用;
  • 标准 I/O 是由文件 I/O 封装而来,标准 I/O 内部实际上是调用文件 I/O 来完成实际操作的;
  • 可移植性:标准 I/O 相比于文件 I/O 具有更好的可移植性,通常对于不同的操作系统,其内核向应用层提供的系统调用往往都是不同,譬如系统调用的定义、功能、参数列表、返回值等往往都是不一样的;而对于标准 I/O 来说,由于很多操作系统都实现了标准 I/O 库,标准 I/O 库在不同的操作系统之间其接口定义几乎是一样的,所以标准 I/O 在不同操作系统之间相比于文件 I/O 具有更好的可移植性。
  • 性能、效率:标准 I/O 库在用户空间维护了自己的 stdio 缓冲区,所以标准 I/O 是带有缓存的,而文件 I/O 在用户空间是不带有缓存的,所以在性能、效率上,标准 I/O 要优于文件 I/O。

2.FILE指针

在前面所介绍的所有文件 I/O 函数(open()、read()、write()、lseek()等)都是围绕文件描述符进行的,当调用 open()函数打开一个文件时,即返回一个文件描述符 fd,然后该文件描述符就用于后续的 I/O 操作。

而对于标准 I/O 库函数来说,它们的操作是围绕 FILE 指针进行的,当使用标准 I/O 库函数打开或创建一个文件时,会返回一个指向 FILE 类型对象的指针(FILE *),使用该 FILE 指针与被打开或创建的文件相关联,然后该 FILE 指针就用于后续的标准 I/O 操作(使用标准 I/O 库函数进行 I/O 操作),所以由此可知,FILE 指针的作用相当于文件描述符,只不过 FILE 指针用于标准 I/O 库函数中、而文件描述符则用于文件I/O 系统调用中。 FILE 是一个结构体数据类型,它包含了标准 I/O 库函数为管理文件所需要的所有信息,包括用于实际 I/O 的文件描述符、指向文件缓冲区的指针、缓冲区的长度、当前缓冲区中的字节数以及出错标志等。

FILE数据结构定义在标准 I/O 库函数头文件 stdio.h 中。

3.标准输入、标准输出和标准错误

关于标准输入、标准输出以及标准错误这三个概念在前面小节有所提及,所谓标准输入设备指的就是计算机系统的标准的输入设备,通常指的是计算机所连接的键盘;而标准输出设备指的是计算机系统中用于输出标准信息的设备,通常指的是计算机所连接的显示器;标准错误设备则指的是计算机系统中用于显示错误信息的设备,通常也指的是显示器设备。 用户通过标准输入设备与系统进行交互,进程将从标准输入(stdin)文件中得到输入数据,将正常输出数据(譬如程序中 printf 打印输出的字符串)输出到标准输出(stdout)文件,而将错误信息(譬如函数调用报错打印的信息)输出到标准错误(stderr)文件。 标准输出文件和标准错误文件都对应终端的屏幕,而标准输入文件则对应于键盘。 每个进程启动之后都会默认打开标准输入、标准输出以及标准错误,得到三个文件描述符,即 0、1、 2,其中0 代表标准输入、1 代表标准输出、2 代表标准错误;

在应用编程中可以使用宏 STDIN_FILENO、 STDOUT_FILENO和 STDERR_FILENO

分别代表 0、1、2,这些宏定义在 unistd.h 头文件中:

/* Standard file descriptors. /
#define STDIN_FILENO 0 / Standard input. /
#define STDOUT_FILENO1 / Standard output. /
#define STDERR_FILENO2 / Standard error output. /

0、1、2 这三个是文件描述符,只能用于文件 I/O(read()、write()等),那么在标准 I/O 中,自然是无法使用文件描述符来对文件进行 I/O 操作的,它们需要围绕 FILE 类型指针来进行,在 stdio.h 头文件中有相应的定义,如下:

/ Standard streams. */
extern struct _IO_FILE stdin; / Standard input stream. */
extern struct _IO_FILE stdout; / Standard output stream. */
extern struct _IO_FILE stderr; / Standard error output stream. /
/ C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr

Tips:struct _IO_FILE 结构体就是 FILE 结构体,使用了 typedef 进行了重命名。 所以,在标准 I/O 中,可以使用 stdin、stdout、stderr 来表示标准输入、标准输出和标准错误。

相关推荐
懒大王敲代码3 分钟前
Uptime Kuma运维监控服务本地部署结合内网穿透实现远程在线监控
运维·docker·colar
荣世蓥3 分钟前
10.1 Linux_并发_进程基本知识
linux·运维·服务器
小白顶呱呱29 分钟前
chatglm本地服务器大模型量化cpu INT4 INT8 half float运行、多卡多GPU运行改这一条指令就行啦!
服务器·大模型·chatglm·gpu算力
默子昂35 分钟前
yolo自动化项目实例解析(七)自建UI--工具栏选项
运维·yolo·自动化
芝法酱1 小时前
芝法酱学习笔记(0.4)——SpringBoot多模块项目打包,resource分离,lib分离,启动脚本
linux·maven·shell脚本·springboot打包·资源分离
深蓝易网1 小时前
为什么优秀的工厂更重视生产现场
大数据·运维·人工智能·数据分析·制造
第六五1 小时前
ubuntu如何开启和关闭图形界面
linux·ubuntu·postgresql
马老师135217304161 小时前
网络安全的岗位分析
运维·安全·web安全·ccrc-dsa·dsa·数据安全评估师
多多*1 小时前
OJ在线评测系统 判题机开发 保证Docker容器执行的安全性
运维·docker·容器
day3ZY1 小时前
谷歌网站收录查询,怎么查看网站在谷歌的收录情况
运维