0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一文搞懂文件描述符

阿铭linux 来源:阿铭linux 2023-02-10 13:56 次阅读

Linux中的文件描述符

我们知道在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。在操作这些所谓的文件的时候,我们每操作一次就找一次名字,这会耗费大量的时间和效率。所以Linux中规定每一个文件对应一个索引,这样要操作文件的时候,我们直接找到索引就可以对其进行操作了。

e699e7d8-a8db-11ed-bfe3-dac502259ad0.png

文件描述符(file descriptor)就是内核为了高效管理这些已经被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符来实现。同时还规定系统刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。这意味着如果此时去打开一个新的文件,它的文件描述符会是3,再打开一个文件文件描述符就是4......

Linux内核对所有打开的文件有一个文件描述符表格,里面存储了每个文件描述符作为索引与一个打开文件相对应的关系,简单理解就是下图这样一个数组,文件描述符(索引)就是文件描述符表这个数组的下标,数组的内容就是指向一个个打开的文件的指针。

上面只是简单理解,实际上关于文件描述符,Linux内核维护了3个数据结构:

进程级的文件描述符表

系统级的打开文件描述符表

文件系统的i-node表

一个 Linux 进程启动后,会在内核空间中创建一个 PCB 控制块,PCB 内部有一个文件描述符表(File descriptor table),记录着当前进程所有可用的文件描述符,也即当前进程所有打开的文件。进程级的描述符表的每一条记录了单个进程所使用的文件描述符的相关信息,进程之间相互独立,一个进程使用了文件描述符3,另一个进程也可以用3。除了进程级的文件描述符表,系统还需要维护另外两张表:打开文件表、i-node 表。这两张表存储了每个打开文件的打开文件句柄(open file handle)。一个打开文件句柄存储了与一个打开文件相关的全部信息。

系统级的打开文件描述符表:

当前文件偏移量(调用read()和write()时更新,或使用lseek()直接修改)

打开文件时的标识(open()的flags参数

文件访问模式(如调用open()时所设置的只读模式、只写模式或读写模式)

信号驱动相关的设置

对该文件i-node对象的引用,即i-node 表指针

文件系统的i-node表:

文件类型(例如:常规文件、套接字或FIFO)和访问权限

一个指针,指向该文件所持有的锁列表

文件的各种属性,包括文件大小以及与不同类型操作相关的时间戳

文件描述符、打开的文件句柄以及i-node之间的关系如下图:

e6ac3960-a8db-11ed-bfe3-dac502259ad0.png

在进程 A 中,文件描述符 1 和 20 都指向了同一个打开文件表项,标号为 23(指向了打开文件表中下标为 23 的数组元素),这可能是通过调用 dup()、dup2()、fcntl() 或者对同一个文件多次调用了 open() 函数形成的。

进程 A 的文件描述符 2 和进程 B 的文件描述符 2 都指向了同一个文件,这可能是在调用 fork() 后出现的(即进程 A、B 是父子进程关系),或者是不同的进程独自去调用 open() 函数打开了同一个文件,此时进程内部的描述符正好分配到与其他进程打开该文件的描述符一样。

进程 A 的描述符 0 和进程 B 的描述符 3 分别指向不同的打开文件表项,但这些表项均指向 i-node 表的同一个条目(标号为 1976); 换言之,它们指向了同一个文件。 发生这种情况是因为每个进程各自对同一个文件发起了 open() 调用。 同一个进程两次打开同一个文件,也会发生类似情况。

这就说明:同一个进程的不同文件描述符可以指向同一个文件; 不同进程可以拥有相同的文件描述符; 不同进程的同一个文件描述符可以指向不同的文件(一般也是这样,除了 0、1、2 这三个特殊的文件); 不同进程的不同文件描述符也可以指向同一个文件。

Linux系统文件描述符示例

比如在Linux上用 vim test.py 打开一个文件,保持打开状态,再新打开一个新的shell,输入命令pidof vim 获取vim进程的pid号,然后 ll /proc/$pid/fd 查看vim 进程所使用的文件描述符列表。

e6c40630-a8db-11ed-bfe3-dac502259ad0.png

/dev/pts是远程登录(telnet,ssh等)后创建的控制台设备文件所在的目录。 因为我是通过Xshell远程登录的,所以标准输入0,标准输出1,标准错误2的文件描述符都指向虚拟终端控制台 /dev/pts/6 。 再看下面是新打开的 test.py 的文件描述符,竟然是4,说好的从3开始呢?

因为vim这种编辑器的原理是先打开源文件并拷贝,然后关闭源文件再打开自己的副本,修改完文件保存的时候直接将副本重命名覆盖源文件。 所以打开源文件的时候用的文件描述符3,然后打开自己的副本是时候就该用文件描述符4了,然后关闭源文件,文件描述符3就被释放了,我们查看的时候就只剩下了4,这里它指向的是vim创建的副本文件。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1362

    浏览量

    40215
  • Linux
    +关注

    关注

    87

    文章

    11219

    浏览量

    208872
  • Linux系统
    +关注

    关注

    4

    文章

    590

    浏览量

    27344
  • 文件
    +关注

    关注

    1

    文章

    561

    浏览量

    24692
  • 描述符
    +关注

    关注

    0

    文章

    3

    浏览量

    6051

原文标题:一文搞懂文件描述符

文章出处:【微信号:aming_linux,微信公众号:阿铭linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    USB描述符详解

    对于实现USB功能的项目,不管是实现CDC,大容量存储、HID等都必须使用实现USB标准描述符,从而实现USB枚举过程。这里共享个USB描述符的详解。
    发表于 06-12 14:46

    传递文件描述符是什么?

    我买了本书《Linux网络编程》。 看到第11章高级套接字。有个例子,传递文件描述符。 其中,进程A根据用户输入的文件名打开
    发表于 05-07 02:18

    ARM中,Linux 文件描述符到底是什么?

    个 Linux 进程启动后,会在内核空间中创建个 PCB 控制块,PCB 内部有文件描述符表(File descriptor tab
    发表于 10-23 16:11

    usb标准描述符之技巧

    usb标准描述符之技巧 USB是个通用的总线,端口都是统的。但是USB设备却各种各样,例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的设备的呢?这就要依赖
    发表于 04-12 11:09 1521次阅读

    USB HID报告及报告描述符简介

    在USB中,USB HOST是通过各种描述符来识别设备的,有设备描述符,配置描述符,接口描述符,端点描述符,字符串
    发表于 04-12 11:13 4002次阅读

    Descriptor描述符解释

    Descriptor即描述符,是个完整的数据结构,可以通过C语言等编程实现,并存储在USB设备中,用于描述个USB设备的所有属性,USB主机是通过
    发表于 07-16 09:39 2619次阅读

    Linux中文件文件描述符概述

    、链接文件和设备文件。 那么,内核如何区分和引用特定的文件呢?这里用到了个重要的概念文件描述符
    发表于 10-18 14:35 0次下载

    USB设备键值表描述符说明资料免费下载

    本文档的主要内容详细介绍的是USB设备键值表描述符说明资料免费下载包括了:1.设备描述符的结构,2. 配置描述符的结构,3. 接口描述符的结构,4. HID
    发表于 07-16 16:56 35次下载
    USB设备键值表<b class='flag-5'>描述符</b>说明资料免费下载

    USB各描述符之间的依赖是怎么样的

    USB 是个通用的总线,端口都是统的。但是USB 设备却各种各样,例如USB 鼠标, USB键盘, U盘等等,那么USB 主机是如何识别出不同的设备的呢?这就要依赖于描述符了。USB 的描述符主要有设备
    发表于 07-23 16:53 8次下载
    USB各<b class='flag-5'>描述符</b>之间的依赖是怎么样的

    Linux系统编程中的文件描述符调用

    文件描述符 进程每打开文件的时候,会获得该文件文件描述
    的头像 发表于 09-02 09:50 1644次阅读
    Linux系统编程中的<b class='flag-5'>文件</b><b class='flag-5'>描述符</b>调用

    科普下什么是USB的描述符

    以及行为呢?这就要通过描述符来实现了。那么什么是USB的描述符呢?其实就是些传递的协议信息,比如设备的类型、厂商ID、产品ID、端点情况、版本号等信息。 既然描述符是协议信息,那么不
    的头像 发表于 12-02 14:41 3908次阅读

    Gadget框架构造描述符

    假设你要【模拟】个 USB 设备: 这个 USB 设备含有厂家信息:它记录在设备描述符里,所以设备描述符应该由你提供 这个芯片可能有多种配置,这也是由你决定,所以配置描述符应该由你提
    的头像 发表于 07-13 11:34 609次阅读
    Gadget框架构造<b class='flag-5'>描述符</b>

    从获取描述符的角度理解Gadget框架

    操作: 使用控制传输,读取设备信息(设备描述符):第次读取时,它只需要得到 8 字节数据,因为第 8 个数据表示端点 0 能传输的最大数据长度。 Host 分配地址给设备,然后把新地址发给设备。 使用新地址,重新读取设备描述符
    的头像 发表于 07-13 11:38 845次阅读
    从获取<b class='flag-5'>描述符</b>的角度理解Gadget框架

    基于DWC_ether_qos的以太网驱动开发-描述符格式介绍

    前面我们介绍了描述符链表的工作模式,重点是了解环形链表是如何环形的,以及相关的寄存器。驱动编写就需要更进步,了解描述符的具体内容,即4个描述符的每个字段的含义。
    的头像 发表于 09-04 14:14 2379次阅读
    基于DWC_ether_qos的以太网驱动开发-<b class='flag-5'>描述符</b>格式介绍

    Python的优雅之处:Descriptor(描述符

    语法糖的实现上也有使用到(在下面的文章会一一介绍)。 当你点进这篇文章时 你也许没学过描述符,甚至没听过描述符。 或者你对描述符只是知半解 无论你是哪种,本篇都将带你全面的学习
    的头像 发表于 11-02 10:52 964次阅读
    Python的优雅之处:Descriptor(<b class='flag-5'>描述符</b>)