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

本文介绍了Linux中文件描述符的概念,作为识别文件的非负整数,其管理和分配规则,并通过示例说明了文件描述符在程序中的作用。同时,讨论了C语言中的FILE结构体,它在用户空间中用于文件操作,并包含文件描述符和缓冲区信息。最后,阐述了文件描述符与FILE结构体之间的关系,以及如何在两者之间进行转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件描述符(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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值