什么是文件描述符?
Posted
技术标签:
【中文标题】什么是文件描述符?【英文标题】:What is file-descriptor? 【发布时间】:2017-04-13 08:51:36 【问题描述】:在尝试学习套接字编程时,我看到了以下代码:
int sock;
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
我浏览了手册页,发现套接字返回一个文件描述符。我曾尝试在这里搜索互联网和其他类似问题,但我无法理解文件描述符的真正含义。如果有人能用简单的语言解释文件描述符,那就太好了。
【问题讨论】:
我建议阅读有关网络编程等复杂主题的结构化介绍。如果您能负担得起一本书或可以访问图书馆,请阅读 Stevens 的 UNIX 环境中的高级编程。 如果您从事大量网络编程,请查看他的网络编程书籍。手册页非常适合作为参考,但对于了解整体想法很差。 【参考方案1】:有两个相关的对象:文件descriptor和文件description。人们经常将这两者混淆,并认为它们是相同的。
文件 descriptor 是应用程序中的一个整数,它引用内核中的文件 description。
文件描述 是内核中维护打开文件状态(其当前位置、阻塞/非阻塞等)的结构。在 Linux 文件中 描述 是 struct file
.
POSIX open():
open()
函数应建立文件和文件描述符之间的连接。它将创建一个引用文件的打开文件 description 和引用该打开文件 description 的文件 descriptor。其他 I/O 函数使用文件描述符来引用该文件。 path 参数指向命名文件的路径名。
open()
函数应返回指定文件的文件描述符,该文件描述符是当前未为该进程打开的最低文件描述符。打开的文件描述是新的,因此文件描述符不应与系统中的任何其他进程共享。
【讨论】:
"文件描述符是应用程序中的一个整数,它引用内核中的文件描述。"有多个文件描述符;它们都引用一个文件描述吗? @Keithdup
为相同的描述创建一个新的描述符,不像open
。【参考方案2】:
文件描述符只是到文件的映射。您也可以说这些是指向进程正在使用的文件的指针。 FD 只是整数值,用作进程资源的指针。
每当一个进程启动时,一个正在运行的进程的条目就会被添加到/proc/<pid>
目录中。这是保存与流程相关的所有数据的地方。此外,在进程启动时,内核会为进程分配 3 个文件描述符,用于与称为 stdin
、stdout
和 stderr
的 3 个数据流进行通信。
linux 内核使用一种算法来始终创建具有最小可能整数值的 FD,因此这些数据流被映射到数字 0
、1
和 2
。
假设在您的代码中您打开了一个要读取或写入的文件。这意味着进程需要访问资源,并且必须为这个新资源创建映射/指针。 为此,内核会在您的代码打开文件后立即自动创建一个 FD。
如果你运行ls -l /proc/<pid>/fd/
,你会看到一个额外的FD创建在那里,ID为4
(如果程序使用了其他资源,也可以是其他数字)
【讨论】:
【参考方案3】:在 Unix/Linux 操作系统中,文件描述符是一个抽象指示符(句柄),用于访问文件或其他 IO(输入/输出)资源,例如管道或网络套接字。 通常,文件描述符索引到由 Linux/Unix 操作系统中的内核维护的每个进程的文件描述符表,然后索引 所有进程打开的文件的系统范围表,称为文件表。 该表记录了打开文件或其他资源的“模式” 对于以下操作(还有更多操作)
阅读 写作 附加 写作可能还有其他模式。 它还索引到第三个称为 inode 表的表,该表描述了实际的底层文件。
【讨论】:
【参考方案4】:我认为文件描述符是(间接的,更高级别的)指针,指向内核维护的不透明文件对象。
通常,当您处理由库维护的对象时,您会将指向您不应该取消引用和自己操作的对象的指针传递给库。
对于内核对象,这不仅仅是你不应该自己操作它们——实际上你不能,因为它们存在于你根本无法访问的不同地址空间中。而且由于它们位于不同的地址空间中,因此指针不会成为一种有意义的引用方式。
您需要一个令牌或句柄,内核将在内部将其解析为在内核地址空间中有意义的指针。文件描述符就是这样的整数形式的标记。
对于内核:
your_process_id + your_file_descriptor => kernels_file_object_pointer
(如果给定的文件描述符可能无法解析为给定进程的文件对象指针,则为 EBADF 错误)
【讨论】:
以上是关于什么是文件描述符?的主要内容,如果未能解决你的问题,请参考以下文章