文件描述符总结
- 什么是文件描述符
- 默认的文件描述符
- 文件描述符的分配原则
什么是文件描述符
Linux系统下, 一切皆文件
在Linux操作系统中系统下, 可以把一切都看做是文件,包括普通文件, 目录文件,套接字等, 将一切都抽象成文件, 提供了统一的接口, 方便程序的调用。
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。
当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件。
通过文件描述符找到文件的流程大体为:
进程打开/创建新文件, 内核向进程返回文件描述符, 文件描述符就相当于files_struct数组的索引,通过该索引获取到文件指针,指向系统级文件描述符表的文件偏移量, 在通过该文件偏移量获取到 inode 节点, 最终获取到文件。
默认的文件描述符
Linux 进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2。
0:表示标准输入,对应宏为:STDIN_FILENO
1:表示标准输出,对应宏为:STDOUT_FILENO
2:表示标准出错处理,对应的宏为:STDERR_NO
文件描述符的分配原则
POSIX标准要求每次打开文件时必须使用当前进程中最小可用的文件描述符号。
以代码为例体会:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
close(0);
//close(2);
int fd = open("myfile", O_RDONLY);
if(fd < 0){
perror("open");
return 1;
}
printf("fd: %d\n", fd);
close(fd);
return 0;
}
结果是:
关闭0 则结果是 fd: 0
关闭2 则结果是 fd:2
所以文件描述符就是在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。