Linux 文件描述符到底是什么东西

  • 这篇博客很长,希望你能看完,是我自己对文件描述符的一些理解,希望能帮助到你

文件描述符

什么是文件描述符

  • 文件描述符是操作系统在进行进程文件管理时,所引入的一种管理方法,这种管理方法是 先描述文件的一系列信息,然后再通过这个文件描述符,进行文件的一些列读写操作

文件描述符在进程中是如何存储的

  • 在进程的PCB中,有专门寸出文件描述符的位置。
  • 在PCB中,有一个*files 的指针,这个指针指向一个名叫 files_struct 的指针数组,这里这个指针数组里存储的就是指向不同文件的指针,既然是一个数组,那就可以通过下标进行数组元素的访问,所以,这里数组的下标的值,就是文件描述符的值。
    在这里插入图片描述
  • 在linux中,一切皆文件,在计算机当中,我们最常接触的就是标准输入和标准输出,还有标准错误输出,这三个在linux中都是以文件的形式存在的,一个进程在开辟的时候,会自动打开这三个文件,存放在 0 1 2 的下标的位置,所以,这三个对应 标准输入,标准输出,标准错误输出。
  • 我们如果在进程中打开文件的时候,系统就会在这个进程的files_struct中添加进对应的文件的指针,然后返回这个文件指针对应的文件描述符,也就是这个文件的下标。我们在进行文件读写操作的时候,如果我们调用的是系统提供的读写操作接口的话,就势必需要使用文件描述符进行操作。(注意,是系统提供的接口,我们在学习语言的时候,其实是通过语言所提供的接口,而非操作系统所提供的接口)这里我画了一个图,帮助你理解系统调用和函数库调用
  • 在这里插入图片描述
  • 系统调用接口,正是绕过了语言所提供的库函数接口,实现了直接面向操作系统的文件操作

文件描述符的一系列操作

  • 如果要直接用文件描述符对文件进行读写操作的话,就需要调用系统提供的接口,系统提供的接口主要有一下几个
  • 文件的打开接口
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

int open(const char* pathname, int flag);
int open(const char* pathname, int flag, mode_t mode);
//参数介绍
flag:
	O_RDONLY:只读打开
	O_WRONLY:只写打开
	O_RDWR :读写打开
	O_CREAT:若文件不存在,就创建一个文件
	O_APPEND:追加写
	注意,以上三个文件,通过‘|’操作符进行组合,达到对应的目的,至于为什么是‘|’,你可以理解为,不同的flag对应不同的 二进制位的1,通过‘|’,可以将这些flag结合起来,达到对应的目的。
	返回值:如果成功,返回对应的文件描述符,如果失败,返回-1
	mode就是权限,对应的0000这四个位的权限,一般设置为0644,如果不进行设置的话,就会随机生成文件的权限。
  • 文件的读写接口
#include<unistd.h>

ssize_t write(int fd, const void* buf,size_t count);
ssize_t read(int fd,void *buf,size_t count);
int close(int fd);
off_t lseek(int fd,off_t offset,int whence);

这里的fd,就是文件对应的文件描述符,可以看到,系统所提供的这几个接口,都是通过文件描述符,
对文件进行的操作。
//////////////////////////////
在write和read函数中,buf就是缓冲区,write通过缓冲区向文件里写数据,read通过缓冲区,
将从文件里读到的数据写入到缓冲区里,然后带回来。 
write和read 的 count都是一次要读或写的期望个数。read的期望数量可以大于你读到的数据的长度,
读到文件的结尾就会自动停止,但是写的话,最多不能超过你所写的数据的长度。
  • 以上就是文件读写操作的一些接口,如何使用这些接口,看接下来的代码
 
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>

int main()
{
    char buf[100];
    int fd_wr = open("hello.txt",O_WRONLY|O_CREAT,0644);//以只写的方式打开文件,
                //如果文件不存在,就创建一个文件。主意路径名,如果你没有写绝对路径的话,
                //就会在当前程序所在的目录下创建文件。
	char *msg = "hello world\n";
 	if(fd_wr < 0)//判断文件是否打开成功
 	{
     perror("open file");
 	}
 	write(fd_wr,msg,strlen(msg));//向文件里写数据
 	close(fd_wr);//关闭文件
//////////////////////////////////////////////////////////////////////////////////
 	int fd_rd = open("hello.txt",O_RDONLY);//以只读方式打开文件
 	if(fd_wr < 0)//判断文件是否打开成功
 	{
    	 perror("open file");
 	}
 	ssize_t s = read(fd_rd,buf,sizeof(buf));//将文件里的数据读入到buf中,并返回读到的字节数
 	buf[s] = '\0';//最读到的字符串最后加0,结尾,方便打印
 	printf("%s",buf);                                                                                                                      
 	close(fd_rd);//关闭文件
 	return 0;
}
  • 以上,便是对文件的基本读写操作,在操作系统中,如果想对文件进行操作的话,利用的就是文件描述符,如果你在输出的时候,向标准输出文件中写数据的话,系统就会将数据写到显示器上,但是,有一点要注意,就是在写完之后,需要将标准输出中缓冲区内的数据刷出来,才能直观的看到所写入的数据

注意事项

  • 文件描述符在分配的时候,并不是按照你打开的文件的顺序进行分配的,而是,从目前能分配的最小的文件描述符进行分配,比如说:你如果关闭了这个进程的标准输入和标准输出,这两个文件的文件描述符就会被释放,然后,再次打开一个新的文件的时候,就会给这个文件分配一个0的文件描述符,占有标准输入的文件描述符的位置。
  • 在进行文件读写操作过后,一定要记得关闭文件。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章