三个标准流
在这篇文章中,我们将从以下三个方面讲述:
- 为什么需要三个标准流
- 为什么默认打开的一定是三个标准流
- 怎么实现:打开这三个标准流
1、为什么需要
程序的核心作用是处理获取进来的数据。那么程序就必须有办法获取数据 ,以及有办法让我们观察数据处理的过程,即能够打印数据。
所以我们就需要有:
stdin:标准输入流。以后用户输入的数据,都将从标准输入流出发,流向程序stdout:标准输出流。以后程序处理数据的结果,若没有特别指定流,默认向标准输出流中流出,最终到达显示设备
现在程序能够获取数据、打印数据。在编写代码,执行代码的时候,我们还希望当程序运行发生错误的时候,有办法将错误的具体信息提炼出来让我们知道,以便后续的调试代码,即能够Debug。
所以我们也需要有stderr标准错误流。如果程序运行发生了错误,具体的错误信息就会写入标准错误流,最终让我们能够获取,从而帮助我们修复代码的错误。
2、为什么一定是"三个"
三个标准流连接的设备,一般是:
stdin···> 键盘stdout···> 显示器stderr···> 也是显示器
既然标准输出流和标准错误流连接的设备都是显示器,那么我们为什么要同时打开stdin stdout stderr三个标准流呢?为什么不只打开stdin stdout?
原因很好理解:我们希望程序的打印信息和错误信息能够分开来,即分离正常和错误。信息糅杂在一起,还需要做一步分离提取的工作;而将打印结果与错误信息分开来,对着错误信息在打印结果找猫腻,能够更快找到Bug,从而提高调试的效率。
3、怎么做到的
机器开机的时候,做的其中一个重要的工作就是将操作系统加载到内存。
而在操作系统加载的过程中,一定有bash父进程被创建,然后加载磁盘文件、显示器文件到内存。
接着连续创建三个struct file对象与磁盘、显示器建立联系,最后在bash进程files_struct的fd_array中,下标0 1 2处分别放入:
- 标准输入文件流
- 标准输出文件流
- 标准错误文件流

这样bash就打开了三个标准流。
bash之后创建的子进程,进行的是对bash父进程的写时拷贝,包括拷贝fd_array。而写时拷贝,fd_array倒是拷贝下来了,但是其中保存的file*指针还是与bash父进程一样的。

可以理解为stdin stdout stderr三个文件file*指针被传递下去了 。所以子进程一旦被创建,默认打开了stdin stdout stderr三个标准流。(就像环境变量和命令行参数一样)
4、修改标准输出流与标准错误流的操作示范
c
#include <stdio.h>
int main()
{
fprintf(stdout, "Hello stdout\n");
fprintf(stderr, "Hello stderr\n");
return 0;
}
bash
./test.exe 1>loga.txt 2>logb.txt

