UNIX文件描述符重用

3

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

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

但是关于进程之间的文件描述符我感到困惑。每个进程是否都有自己的0/1/2描述符用于输入/输出/错误,还是这3个描述符在所有进程之间共享?如果你在3个不同的shell中运行3个程序,它们如何只获取各自程序的输出,而不是其他程序的输出呢?

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

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


如果您在发布时添加一个“c”语言标签,您将获得更好的评论。我认为我已经看到这个问题被讨论了很多次,所以请搜索“[c] stdout dup descriptors”。祝你好运。 - shellter
谢谢,我已经添加了标签 - 我也会尝试查看其他问题的 :) - John Humphreys
3个回答

5

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

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

回答您的问题,两个程序都将对新打开的文件具有FD#3。


3

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

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

foo | bar

在这种情况下,foo的标准输出必须连接到bar的标准输入。为此,Shell 最可能使用 pipe() 来创建读者和写者文件描述符。它进行两次 fork()。描述符将一直存在。将调用foo 的 fork(),会关闭(1); dup(writer_fd); 以使 writer_fd 描述符变成 1。然后它将执行 exec() 函数,并且处理 foo 将输出到我们创建的管道中。对于 bar,我们关闭(0); dup(reader); 然后执行 exec() 函数。voila,foo 将会输出到 bar 中。

3
进程从不共享描述符。但是,多个文件描述符(可以在同一进程或不同进程中)可以引用相同的“打开文件描述符”,该描述符具有共享属性,如当前位置、非阻塞标志等。 - R.. GitHub STOP HELPING ICE

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接