您的位置:首页 > 运维架构 > Linux

Linux---文件描述符fd与FILE结构体

2018-01-31 13:54 281 查看
4000

文件描述符(file descriptor)

在Linux中不是用文件指针来识别一个文件,而是用文件描述符来识别的。

文件描述符简称fd,它是Linux内核所创建的索引,目的就是为了高效管理已经被打开的文件。它是一个非负整数,用来表示被打开的文件,而对该文件所有的I/O操作都是通过该文件的文件描述符来执行的。

在一个程序刚刚启动时,系统就已经占了三个文件描述符了,分别为:0(标准输入)、1(标准输出)、2(标准错误)。如果此刻程序再打开或创建一个新文件时,该文件的文件描述符将是3。因为文件描述符有自己的分配规则:将当前最小的未被使用的文件描述符分配给新创建的文件。

来一张图看看文件描述符是怎么管理文件的:



如果我们关闭了文件描述符1呢?来看一段代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
close(1);
int fd=open("file",O_CREAT|O_WRONLY,0644);
if(fd<0)
{
perror("open");
exit(1);
}
printf("fd=%d\n",fd);
fflush(stdout);

close(fd);
exit(0);
}


来看看运行结果:



我们可以看到运行程序之后,多了一个我们创建的文件file,用cat命令查看文件的内容,发现本该输出到屏幕上的语句却写到了打开的文件里,而且文件描述符是1

FILE结构体

c语言的stdio.h头文件中,定义了用于文件操作的结构体FILE。因此我们通过fopen返回一个文件指针(指向FILE结构体的指针)来进行文件操作。文件指针指向进程的用户空间中的FILE结构体。

可以在stdio.h(位于visual studio安装目录下的include文件夹下)头文件中查看FILE结构体的定义,如下:

FILE结构体中最重要的两个成员变量是:文件描述符和缓冲区的大小

//C语言文件指针域文件描述符之间可以相互转换
int fileno(FILE * stream)
FILE * fdopen(int fd, const char * mode)

struct _iobuf {
char *_ptr;          //文件输出的下一个位置
int   _cnt;          //当前缓冲区的相对位置
char *_base;         //缓冲区基址
int   _flag;         //文件标志
int   _file;         //文件描述符
int   _charbuf;      //检查缓冲区状况,若无缓冲区则不读取
int   _bufsiz;       //缓冲区大小
char *_tmpfname;     //临时文件名
};
typedef struct _iobuf FILE;


c程序用不同的FILE结构体管理每个文件。程序员可以使用文件,但是不需要知道FILE结构体的细节。实际上,FILE结构体是间接地操作系统的文件控制块(FCB)来实现对文件的操作的。

FILE结构体中的_file ,也就是文件描述符,作为进入打开文件表索引的整数。

文件描述符和FILE结构体的关系

在Linux下编程常需要对一些文件进行操作。有时不同的条件下,需要将文件指针即句柄(FILE*)、文件描述符(fd)以及文件路径(filepath)进行相互转换,以满足实际的编程需要。

文件路径 文件描述符应是唯一的。文件指针(值)不是唯一的,但指向的对象也应该是唯一的

FILE* 中包含fd的信息,而且还包含IO缓冲,所以可以理解为 FILE* 是对fd的封装,是C的标准形式,所以FILE* 比fd更适合跨平台,应多用fopen,少用 open。

文件描述符 到 文件指针:fd–fdopen()–>FILE*

文件指针 到 文件描述符:FILE*–fileno()—>fd
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: