在学习文件描述符以前,咱们先来看一点其它相关的知识点。数组
咱们都知道,对一个文件咱们能够进行打开、读、写、关闭操做,在咱们没有接触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。