目录
编辑由结果知:fd1指向文本文件cyq.txt,原本fd1是默认被fd_array[2]指向的,现在fd1却被fd_array[0]指向了。
方法3:符号形式的重定向—— “ > ” 、 “ >> ”、“ < ”
实验案例:该案例将围绕123.txt文件内容为中心理解符号形式的重定向实现
前言:
之前,我讲解了Linux下文件的特性、讲解了关于Linux关于文件的系统调用函数open、write、read、close函数,讲解了它们与C语言库中fopen、fclose、fgets、fputs等函数的区别,其实fopen、fclose、fgets、fputs这些函数是在Linux系统调用函数的底层原理下封装形成的优化C库函数。
接下来,我将继续深入讲解Linux中文件的一些底层知识。
首先来回顾一下open函数,即在进程中同时打开多个文件:
#include<errno.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#define Filename1 "big1.txt"
#define Filename2 "big2.txt"
#define Filename3 "big3.txt"
#define Filename4 "big4.txt"
int main(){
//同时打开多个文件
int f1=open(Filename1,O_CREAT| O_WRONLY |O_TRUNC,0664);
int f2=open(Filename2,O_CREAT| O_WRONLY |O_TRUNC,0664);
int f3=open(Filename3,O_CREAT| O_WRONLY |O_TRUNC,0664);
int f4=open(Filename4,O_CREAT| O_WRONLY |O_TRUNC,0664);
//打印这些文件描述符的值
printf("f1: %d\n",f1);
printf("f2: %d\n",f2);
printf("f3: %d\n",f3);
printf("f4: %d\n",f4);
close(f1);
close(f2);
close(f3);
close(f4);
return 0;
}
运行结果:
从结果中,我们看到这4个文件描述符的值分别是3-6,那么有人会想为什么是从3开始往后呢?为什么不是从1开始,或者从0开始呢?
其实这就要说到标准流了! 我们在学C语言的过程中,相必从书中就已经了解到了多种流,它们分别是标准输入流stdin、标准输出流stdout、标准错误流stderr,这三种流分别对应键盘、显示器、显示器。stdin标准输入流就是通过键盘向计算机中写入数据的;stdout标准输出流是通过读取计算机中的正常运行得出的数据到显示器中,方便查看的;stderr标准错误流是读取计算机在运行过程中产生的错误信息到显示器中。
Linux下一切皆文件,那么这三个流也不例外,它们也是文件,而且它们三个是处于一直被打开的状态,因为每个进程的运行都离不开它们几个,于是stdin、stdout、stderr所代表的也是文件描述符,每个进程都有一个文件描述符表,它相当于一个数组,专门用于存放该进程打开的各个文件。这三个文件描述符就占据了数组的榜一榜二榜三位置,导致后面被进程打开的文件只能从数组索引位置3开始!
求证一下:
结果运行:
Linux底层进程与文件的关系 :
每个进程都有一个task_struct的结构体,该结构体中存放着该进程的各个属性,既然一个进程打开了多个文件,那么这几个被该进程打开的文件就必须要被管理和维护,所以task_struct的进程属性中就又多了一个属性:file_struct* files指针,该指针指向记录着该进程所打开的所有文件的结构体:files_struct。
Linux下一切皆文件的本质和 “先描述,再组织 ” 的核心管理理念,使得我们能够清楚的了解到这个结构体中包含着每个被打开文件的各个属性,其中的成员file* fd_array[ ]指针数组便是存放着文件的各个文件描述符。所以本质上,文件描述符就是指针数组的下标。所以进程和被打开文件的关系就是通过文件描述符表files_struct映射的。
二.重定向的实现
什么是重定向?
重定向就是说改变数据的流向!举个例子大家就明白了:有一家厂商给超市供大量货物时,由于厂商偷工减料赚黑心钱,被超市发现后立即停止该家厂商继续供货,另外寻找其他厂商商量超市货物供应。这就是重定向,在原本的基础数据流程方向上进行转换,重新选择新的数据流程方向。
重定向的实现共有三种方式,其中两种是需要在程序中使用代码去实现重定向,还有一种就是直接使用>、>>、<符号去实现重定向。
方法1:
既然stdin,stdout,stderr这三个流的类型也是文件,那么意味着它们可以被close,假如我们关闭了file* fd_array[ ]数组中的前3个标准流,会发生什么?
2.1关闭stdin:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
close(0); //关闭stdin流
int fd1=open("cyq.txt",O CREAT O WRONLY O TRUNC,0666);
if(fd1<0){
perror("open");
exit(-1);
}
printf("open fd1: %d\n", fd1);
close(fd1);
return 0;
}
由上面代码可知:关闭了文件描述符表中数组的首元素,意味着fd_array[0]不再指向stdin——键盘,那么该数组的首元素为空。