C语言 是否可以静态定义 std in/out/err 以外的文件描述符



大多数开发人员都会意识到进程定义了三个文件描述符,我们通常将其称为stdinstdoutstderr

据我所知,每个fd分别静态定义为 0、1 和 2。这在POSIX标准中明确规定:http://pubs.opengroup.org/onlinepubs/009695399/functions/stdin.html

现在假设我有一组需要第四个进程。 例如,使用 fork() exec() 创建的子进程需要对在fork()之前使用 socketpair() 创建的控制套接字的句柄。 对于此示例,第 4 个句柄(套接字(的目的是在父进程和子进程之间提供链接。 现在问题来了...孩子如何知道哪个FD是控制插座? 有什么理由不能为此使用静态数字(例如:#define CONTROL_SOCKET 3(,只要我在fork()exec()之间dup2(new_socket,CONTROL_SOCKET)。 然后我就可以foo = write(CONTROL_SOCKET, bar, baz)孩子里面了。让我们把它读成任何其他打开我的应用程序的FDs都应该在 exec 上关闭,所以我的逻辑是dup2()不会关闭任何无论如何都不会被 exec() 关闭的东西。

我知道有几种可能的解决方法可以避免这样做(例如:在环境变量或程序参数中传递FD(,并且网络上有许多示例显示了如何做到这一点。 我不明白的是正在解决什么问题? 静态定义要避免的 FD 有什么问题? 乍一看,感觉是在避免一个不存在的问题。 某些系统是否使用 0、1 和 2 以外的 FD,我是否会通过在执行官之前dup2(<some fd>,3)来覆盖重要内容?

注意:这个问题实际上是一个关于编写在现有POSIX操作系统之间可移植的代码的问题。

除了 0、1、2 之外,没有广泛使用文件描述符。 我似乎记得一些跟踪系统使用了超出该范围的固定文件描述符(尽管通常不是 3 个(,但它们是非常例外(我不记得这个千年注意到它(。

总的来说,如果集合中的第一个进程能够确保描述符在启动时未被使用,则可以安全地将描述符传递给其子进程。 如果发现描述符已在使用中,则可以打开控制套接字的其他描述符,然后使用 fstat() 比较这两个描述符。 如果它们适用于同一设备,则可以继续使用继承的描述符 3;如果没有,则需要dup2()close()控制插座。

如果您的进程计划仅自己打开控制套接字,则无需特别担心使用哪个文件描述符。

您可能

不想这样做的原因是,与012不同,您无法保证3将打开,除非您始终控制进程的启动方式。

不过,为某些频道设置固定的描述符编号并没有错。你绝对不会用dup2(<some fd>, 3)覆盖任何东西.它只会掩盖您的进程及其子进程的<some fd>,但 3 在父进程中根本不会受到影响。

你不需要让它变得那么复杂。

即不要将dup2()与目标描述符一起使用,您不知道目标描述符是否关闭(例如,您知道是因为您刚刚关闭了它(,或者您不想在这样做时隐式关闭。

只需new_socket本身作为表示其整数值的字符串,在命令行或环境变量中传递,如注释中所建议的那样。

看到这个答案:https://stackoverflow.com/a/21596854/816536 但忽略"P1.c"的第二个变体 - 这是失败的方式。

最新更新