Linux——文件描述符(fd)与重定向、dup/dup2

目录

一.文件描述符

(一).含义

(二).使用

(三).标准输入/输出/错误

二.重定向与dup/dup2

(一).dup/dup2 

(二).重定向 


一.文件描述符

(一).含义

文件描述符(file descriptor)简称为fd,其本质就是一个数组下标

当创建一个进程时,操作系统不仅会创建task_struct结构体(PCB进程控制块),还会创建一个files_struct结构体用于表示该进程打开的相关文件。进程控制块中有一个指针会指向该files_struct。

 在files_struct结构体内部,有一个结构体指针数组fd_array。fd_array是一个数组,里面存放的是指针,每一个指针都指向一个file结构体。

文件描述符fd就是fd_array的数组下标。

(二).使用

以c语言fwrite函数为例,fwrite内部通过FILE结构体找到文件描述符fd,同时调用系统接口write。

操作系统根据调用的write的进程,通过task_struct结构体内部指针,找到files_struct,再通过files_struct内的fd_array指针数组,依照write传入的具体fd值(下标),找到对应的file结构体,就找到了相关文件。

图例如下:

当进程打开一个文件时,系统就会在fd_array内部从0下标开始依次寻找尚未指向具体file的指针(空指针),将该文件的file结构体给这个指针。 

关闭一个文件时,fd_array中相关指针会指向空,当再其他文件打开时,按照从0开始寻找空指针的方式,找到该空指针,让其指向新的文件。

(三).标准输入/输出/错误

名称 硬件 FILE* fd
标准输入 键盘 stdin 0
标准输出 显示器 stdout 1
标准错误 显示器 stderr 2

以C语言为例,<stdio.h>头文件内部已经提前打开了三个文件(两个硬件:键盘、显示器)。

即标准输入、标准输出、标准错误。依照fd_array对文件描述符的分配规则,从0下标开始依次指向具体的file。这也就是为什么标准输入、标准输出、标准错误的fd默认为0、1、2。

所以,下面代码也就很好理解了:

int main()
{
	const char* str = "hello world\n";
	fwrite(str, strlen(str), 1, stdout);
	return 0;
}

stdout是<stdio.h>头文件定义的表示显示器的FILE指针,指针指向的FILE结构体内部fd值为1,因此fwrite直接通过stdout这个指针获得相关fd,进而使用显示器。

二.重定向与dup/dup2

有了对于文件描述符的理解, 重定向的概念就很好理解了。

(一).dup/dup2 

这种替换可以通过系统接口dup2完成。

不管是dup还是dup2因为是系统接口,其参数均是文件描述符fd。 

dup可以返回一个新的fd来表示传入的oldfd所代表的文件,即赋予该文件另一个fd。

dup2可以将oldfd所代表的文件给newfd,如果两个fd所代表的文件本就相等,那将不做任何改动。

dup2在使用时常常容易搞错复制方向,可以这样理解:dup2(copy from, copy to)

 如果调用失败,均返回-1。

(二).重定向 

重定向本质是使fd_array中指向原文件的指针指向目标文件。 

 以标准输出重定向为例:

[cdl@VM-16-9-centos ~]$ echo "hello world" > file.txt

本质就是将fd_array中原本指向显示器file的指针指向file.txt的file结构体,即:

FILE* file = fopen("./file.txt", ...);
dup2(file._fileno, 1);

echo还是将数据给fd为1的指针指向的文件,但因为fd=1的指针指向了file.txt(的file结构体),因此echo把数据给了file.txt。 

图示如下:

追加重定向就是在打开file.txt文件时就赋予文件追加属性,相当于这样:

//系统open接口,O_TRUNC:按追加方式打开文件
int fd = open("./file.txt", O_CREAT | O_RDWR | O_TRUNC);

愚者困惑,智者提问——Benjamin Disraeli


如有错误,敬请斧正

猜你喜欢

转载自blog.csdn.net/weixin_61857742/article/details/127835592