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),这些实质上是系统调用接口,至关于被库函数进行了一次封装。学习

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

1、文件描述符操作系统

(1)概念code

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

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

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、一、2三个文件时,下一次当操做系统打开一个新的文件时,会默认从文件描述符没有使用的最小下标开始。(例如关闭了0,下一次打开一个新的文件时,该新文件描述符为0),说到这里,咱们很容易产生一些疑问,这是怎么回事,下面,咱们再来看一个概念来解决咱们的疑惑吧!

2、重定向

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。