1

我是C下进程使用的新手,我有与子进程中文件描述符的linux行为有关的问题。

我发现了文件描述符在子进程和父进程之间共享的信息,数字 0,1,2 的文件描述符是标准输入输出和错误,所以我认为如果我分叉该进程我会有相同的输入和输出目录,但是当我在子进程中更改它时,它们在父进程中不会更改。我的问题是,它是否适用于每个文件描述符,所以如果我决定让我们说在子进程中覆盖文件描述符编号 100,它在子进程和父进程中会有所不同,或者只有文件描述符 0、1、2 被认为是特殊的。

最好的祝福

4

3 回答 3

7

POSIX 线程实际上与具体关系不大,fork所以我假设您在谈论进程而不是线程。使用线程,没有父子概念,它们共享相同的数据。

对于进程,每个进程都有自己的一组唯一的文件描述符,一个小的非负数(不是文件句柄,这是 C 的概念)。

但是,这些文件描述符都指向共享池中的条目(例如,在内核内部)。这允许所有进程拥有自己的标准输入、输出和错误(描述符 0、1 和 2),但它们可能引用相同的“支持文件”。

因此,当您的进程分叉时,它会获得自己的文件描述符,但它们指向与父进程相同的共享池条目。

如果孩子然后去关闭它的文件描述符并重新打开它以指向其他地方,那只会影响孩子,而不是父母。

因此,假设您有三个进程作为两个分叉的结果,并且进程 C 已关闭并重新打开其标准输出以转到文件。这是关于您所处情况的(某种)图形指示:

Individual processes          Shared pool
          +------+            +------------------+
Process A | fd 1 | ----+----> | maps to /dev/tty |
          +------+     |      +------------------+
Process B | fd 1 | ----+
          +------+            +------------------+
Process C | fd 1 | ---------> | maps to new file |
          +------+            +------------------+

这种行为对于三个标准描述符没有任何特别之处,它适用于它们。事实上,描述符不仅存在于 afork中,它们(通常)也存在于a 中exec,这使得重定向在类 UNIX 操作系统下工作。如果你想让它自动关闭,你必须显式地标记一个描述符exec

于 2013-06-14T03:11:04.103 回答
1

您可以将文件描述符视为数组的索引。因此,标准输入/输出/错误的描述符实际上并没有什么特别之处。

一旦你分叉了这个过程,就会有两个这样的数组,一个用于父级,一个用于子级。由于它被复制,它们一开始都是相同的,但是一旦不同的进程开始打开和关闭其他文件描述符,它们就会开始分歧。

于 2013-06-14T03:11:03.007 回答
1

子进程在 时获得父进程打开的文件表的副本fork(),但在那之后父进程或子进程中的任何更改(例如打开新文件描述符或关闭现有文件描述符)都不会反映在另一个中。在这方面,文件描述符 0、1 和 2 没有什么特别之处。

但是请注意,即使打开文件表(即文件描述符集)被复制,这些描述符引用的打开文件也不会被复制。这意味着对打开文件的更新(例如,用 更改当前文件位置lseek())会影响这两个进程。

线程是另一回事。同一个进程中的线程共享同一个打开文件表,因此一个线程的变化被所有线程看到。同样,在这方面,文件描述符 0、1 和 2 没有什么特别之处。

于 2013-06-14T03:18:37.230 回答