UNIX 文件描述符重用

Posted

技术标签:

【中文标题】UNIX 文件描述符重用【英文标题】:UNIX File Descriptors Reuse 【发布时间】:2011-10-30 06:04:16 【问题描述】:

虽然我习惯了 UNIX 并且已经在上面编程了很长时间,但我不习惯文件操作。

我知道 0/1/2 文件描述符是标准的输入、输出和错误。我知道,每当一个进程打开一个文件时,它都会被赋予一个尚未使用的最小值的描述符 - 我了解一些关于使用 dup/dup2 的事情。

我对进程之间的文件描述符感到困惑。每个进程是否都有自己的 0/1/2 描述符用于输入/输出/错误,或者这 3 个描述符是否在所有进程之间共享?为什么你可以在 3 个不同的 shell 中运行 3 个程序,而如果它们是共享的,它们都只能得到它们的程序输出?

如果两个程序在启动后打开 myfile.txt,它们会都使用文件描述符 #3,还是第二个程序使用 #4,因为使用了 3?

我知道我在那里以几种方式问过同样的问题,但我只是想清楚一点。越详细越好:)我在编程时从来没有遇到过这些问题,但是我正在阅读一本 UNIX 书籍以了解更多信息,我突然意识到这让我很困惑,我从来没有想过它之前的细节。

【问题讨论】:

如果您在帖子中添加“c”语言标签,您将获得更好的 cmets。我想我已经多次看到这个讨论,所以搜索“[c] stdout dup 描述符”。祝你好运。 谢谢,添加标签 - 我也会尝试查看其他问题 :) 【参考方案1】:

每个文件描述符都是进程本地的。但是,某些文件描述符可以引用同一个文件——例如,如果您使用fork() 创建一个子进程,它将共享父进程打开的文件。它将有自己的一组文件描述符,最初与父文件描述符相同,但它们可以随着关闭/复制等而改变。

如果两个程序打开同一个文件,通常它们会得到不同的文件描述符,指向不同的内部结构。但是,使用某些技术(fork、FD 传递等),您可以让不同进程中的文件描述符指向同一个内部实体。但是,通常情况并非如此。

回答您的问题,这两个程序都有 FD #3 用于新打开的文件。

【讨论】:

【参考方案2】:

Unix 中的文件描述符(通常)通过 fork() 和 exec() 调用持续存在。所以是的,多个进程可以共享文件描述符。

例如,shell 可能会执行如下命令:

foo | bar

在这种情况下,foo 的标准输出必须连接到 bar 的标准输入。为此,shell 很可能会使用 pipe() 来创建读写器文件描述符。它 fork() 两次。描述符持续存在。调用 foo 的 fork() 将 close(1);重复(writer_fd);制作 writer_fd 描述符 1. 然后它将执行 exec(),进程 foo 将输出到我们创建的管道。对于 bar,我们 close(0);重复(读者);然后执行()。瞧,foo 将输出到 bar。

【讨论】:

进程从不共享描述符。然而,多个文件描述符(在同一个进程或不同进程中)可以引用同一个“打开文件描述”,它具有当前位置、非阻塞标志等共享属性。【参考方案3】:

不要将文件描述符与它们所代表的资源混淆。您可以有十个不同的进程,每个进程都打开一个文件描述符“3”,每个进程都引用一个不同的打开文件。当一个进程使用其文件描述符执行 I/O 时,操作系统知道哪个进程正在执行 I/O,并且能够区分引用的是哪个文件。

【讨论】:

以上是关于UNIX 文件描述符重用的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Linux 会重用 pipe() 分配的文件描述符

Unix系统编程()文件描述符和打开文件之间的关系

C语言(socket)close()函数(关闭文件描述符,使其不再引用任何文件并且可以重用)

通过 Unix Domain Socket 传递文件描述符

通过UNIX域套接字传递文件描述符

UNIX再学习 -- 文件I/O