C POSIX进程和文件描述符

C POSIX进程和文件描述符,c,linux,posix,C,Linux,Posix,我是C下进程使用的新手,我有一个与子进程中文件描述符的linux行为相关的问题 我发现文件描述符在子进程和父进程之间共享,并且数字为0,1,2的文件描述符是标准的输入输出和错误, 所以我认为如果我分叉进程,我将拥有相同的输入和输出目录,但是当我在子进程中更改它时,它们在父进程中不会更改。我的问题是,它是否适用于每个文件描述符,因此,如果我决定在子进程中覆盖文件描述符编号100,那么子进程和父进程中的文件描述符编号将不同,或者只有文件描述符0、1、2被认为是特殊的 最重要的是您可以将文件描述符视为

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

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


最重要的是

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


一旦你完成了这个过程,就会有两个数组,一个用于父数组,一个用于子数组。它们在开始时都是相同的,因为它被复制了,但是一旦不同的进程开始打开和关闭其他文件描述符,它们就会开始分离。

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


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

POSIX线程实际上与
fork
没有什么特别的关系,所以我假设您谈论的是进程而不是线程。对于线程,没有父线程和子线程的概念,它们共享相同的数据

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

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

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

如果子对象随后关闭其文件描述符并将其重新打开到其他位置,则只会影响子对象,而不会影响父对象

假设您有三个进程作为两个fork的结果,而进程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 |
          +------+            +------------------+

这一行为对于三个标准描述符来说绝非特别,它适用于所有这三个描述符。事实上,描述符不仅在
fork
中存活,而且(通常)在
exec
中存活,这使得重定向在类UNIX操作系统下工作。如果希望在
exec

上自动关闭描述符,则必须显式标记描述符。POSIX线程实际上与
fork
没有什么特别的关系,因此我假设您讨论的是进程而不是线程。对于线程,没有父线程和子线程的概念,它们共享相同的数据

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

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

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

如果子对象随后关闭其文件描述符并将其重新打开到其他位置,则只会影响子对象,而不会影响父对象

假设您有三个进程作为两个fork的结果,而进程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 |
          +------+            +------------------+
这一行为对于三个标准描述符来说绝非特别,它适用于所有这三个描述符。事实上,描述符不仅在
fork
中存活,而且(通常)在
exec
中存活,这使得重定向在类UNIX操作系统下工作。如果要在
exec

上自动关闭描述符,则必须显式标记描述符。子进程在
fork()
时获取父进程打开的文件表的副本,但在此之后,父进程或子进程中的任何更改(例如打开新文件描述符或关闭现有文件描述符)都没有反映在其他方面。在这方面,文件描述符0、1和2没有什么特别之处

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

对于线程来说,这是另一回事。同一进程中的线程共享同一个打开的文件表,因此所有线程都可以看到一个线程中的更改。同样,文件描述符0、1和2在这方面也没有什么特别之处。

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