1.初识文件描述符
文件描述符(File Descriptor,简称FD)是一个非负整数,用于标识已打开的文件或其他I/O资源。在Linux系统中,文件描述符是内核为了高效管理已打开的文件所创建的索引。每个进程都有一个文件描述符表,用于记录进程使用的文件描述符和相关信息。
在Linux系统中,一切皆文件,文件描述符是内核为了高效管理已打开的文件所创建的索引。文件描述符是一个整数,用于指代被打开的文件。所有执行I/O操作的系统调用都是通过文件描述符完成的。
那么我们怎么正面文件描述符是存在的呢?
这里我们使用Linux下的系统调用函数“o在这里插入代码片
pen”,当然说是系统调用,实际上open也是c语言进行实现的,但是他是用与每种语言实现不同的文件操作系统使用的最小的接口单位。
2.证明文件描述符
先来介绍一下open函数的操作及使用
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
int main()
{
int fd1 = open("log.txt",O_CREAT | O_WRONLY | O_TRUNC , 0666);
int fd2 = open("log1.txt",O_CREAT | O_WRONLY | O_TRUNC , 0666);
int fd3 = open("log2.txt",O_CREAT | O_WRONLY | O_TRUNC , 0666);
int fd4 = open("log3.txt",O_CREAT | O_WRONLY | O_TRUNC , 0666);
printf("%d\n%d\n%d\n%d\n",fd1,fd2,fd3,fd4);
close(fd1);
close(fd2);
close(fd3);
close(fd4);
return 0;
运行后得到结果:
3.剖析文件描述符
那么这些数字又是什么呢?为什么数字从三开始的呢?
答案是:第一这些数字就是文件描述符,用来对打开文件进行管理操作的索引。第二,在C语言程序启动的初始化阶段,系统会自动帮我们启动标准输入、标准输出、标准错误三个文件,这三个文件分别对应的就是0,1,2三个文件描述符。这下就都解释通了。
我们怎么理解文件描述符呢?
在这里我给大家画了一幅进程在运行时操作系统内部的流程,每个进程在运行时都会先创建一个task_struct作为控制进程的一个结构体,在这个结构体中,有很多数据,其中struct_file* 指向一个指针数组,内部记录了每一个进程所打开的文件。文件从磁盘加载到内从中,首先是先把文件内容加载到文件缓冲区,如果我们对我呢见进行修改的话,就是从文件缓冲区中copy一份到用户空间中(当然这里中间还有很多细节,相对来说不算标准,但是对于刚学习文件系统的同学可以更好的理解,后面说到Page Cache详说)再进行修改后重新写入。
4.利用文件描述符简写Linux下的重定向
那么我们怎么来做Linux下重定向这段代码呢?
相信说到这里大家已经有一些印象了,我们在上面的代码中可以关闭我们的文件,那么在Linux下一切皆文件,我们当然也可以关闭标准输入、标准输出文件了,然后在将我们向显示屏上打印内容的标准输出文件替换成我们别的文件描述符,这样我们不就可以将想写到显示器的内容写到文件里面了嘛。
开始实操:
给大家介绍一个函数dup2
dup2可以改变文件描述符的指向。
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
int main(int argc,char* argv[])
{
if(argc != 2)
{
printf("Usage:%s",argv[0]);
return 1;
}
umask(0);
int fd = open(argv[1],O_CREAT | O_WRONLY | O_TRUNC ,0666);
if(fd<0)
{
perror("open");
return 1;
}
dup2(fd,1);
const char* meg = "hello bit";
int cnt = 5;
while(cnt--)
{
char buffer[16];
snprintf(buffer,sizeof(buffer),"%s\n",meg);
write(1,buffer,strlen(buffer));
}
close(fd);
return 0;
}
这里是一个简单的重定向代码,我们可以这样大家就可以观察到我们原本是向文件描述符为1的文件中写入,而经过上面证明1是我们的标准输出,本来应该是打印到显示器上面,但是我们一运行这段代码,发现出现了一个文件,并且与其输入的内容出现在文件中。
文件描述符就讲到这里goodbey!