Linux基础IO--文件描述符fd/重定向

在学习文件描述符之前,我们先来看一点其它相关的知识点。

我们都知道,对一个文件我们可以进行打开、读、写、关闭操作,在我们没有接触Linux之前,将信息输出到显示器上,我们通常能想到的方法有以下几种:

#include<stdio.h>
#include<string.h>

int main()
{
	char *msg = "hello world!\n";
	fwrite(msg, strlen(msg), 1, stdout);
	printf("hello world!\n");
	fprintf(stdout, "hello world!\n");
	return 0;
}

C语言会默认帮我们打开stdin、stdout、stderr这三个流,并且,这三个流的类型都是FILE*型的。

其实,上面三种方式,我们都是调用的C标准库函数,但在Linux中也有这些操作,而它们都没有带“f”(例如open、read、write、close),这些实质上是系统调用接口,相当于被库函数进行了一次封装。

接下来,我们来总结一下“文件描述符”的相关知识点!

一、文件描述符

(1)概念

1.所谓文件描述符,其实就是一个小整数;

2.Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输入1,准本错误2;

3.0,1,2,对应的物理设备一般是:键盘、显示器,输入、输出还可以采用如下方式;

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<string.h>
  6 
  7 int main()
  8 {
  9     char buf[1024];
 10     ssize_t s=read(0,buf,sizeof(buf));
 11     if(s>0){
 12         buf[s]=0; 
 13         write(1,buf,strlen(buf));
 14         write(2,buf,strlen(buf));
 15     }
 16     return 0;
 17 }

(2)相关图


从这张图,我们不难看出,文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述文件,于是就有了file的结构体,此时已经打开相应文件对象。

而且从上图不难看出,文件描述符本质上就是数组的下标,因此,只要拿着文件描述符,就可以找到对应的文件

(3)文件描述符的分配规则

下面我们来看一段代码

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 
  6 int main()
  7 {
  8     int fd=open("myfile",O_RDONLY);
  9     if(fd<0){
 10         perror("open");
 11         return 1;
 12     }
 13     printf("fd:%d\n",fd);
 14     return 0;
 15 }

输出结果:fd:3。这也就验证了上面所说的一句话,操作系统会默认打开0,1,2,三个文件,存放stdin、stdout、stderror、当我们再打开一个文件时,它的文件描述符会从3开始。

其实,除了这种情况以外,还有一种情况,当关闭了0、1、2三个文件时,下一次当操作系统打开一个新的文件时,会默认从文件描述符没有使用的最小下标开始。(例如关闭了0,下一次打开一个新的文件时,该新文件描述符为0),说到这里,我们很容易产生一些疑问,这是怎么回事,下面,我们再来看一个概念来解决我们的疑惑吧!

二、重定向

1.常见的重定向有:>(输出重定向)、>>(追加重定向)、<(输入重定向)

2.以输出重定向为例,我们来看一段代码:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/stat.h>
  4 #include<fcntl.h>
  5 #include<stdlib.h>
  6 
  7 int main()
  8 {   
  9     close(1);
 10     int fd=open("myfile",O_WRONLY|O_CREAT,0644);
 11     if(fd<0){
 12         preeor("open");
 13         return 1;
 14     }
 15     printf("fd:%d\n",fd);
 16     fflush(stdout);
 17     close(fd);
 18     exit(0);
 19  
 20 }

我们会发现,本应该输出到显示器上面的内容,却输出到了文件myfile当中,其中文件myfile的fd为1,这就是所谓的输出重定向。

3.重定向的本质


一般printf往stdout中输出,但是stdout在底层访问文件的时候,找的还是fd=1,但此时fd:1下标所表示的内容,已经变成了myfile的地址,不再是显示器文件的地址,所以,输出的任何消息都会往文件中写入,进而完成输出重定向。

通过上面的学习,我们都知道访问文件都是通过fd访问的,因此C标准库中的FILE结构体内部,必定封装了fd。

猜你喜欢

转载自blog.csdn.net/cherrydreamsover/article/details/79656356