正如大多数开发人员所知,流程定义了三个文件描述符,我们更常见的是stdin
,stdout
和stderr
。
从我所知的fd
中,每一个都分别静态定义为0,1和2。这在POSIX标准中明确说明:http://pubs.opengroup.org/onlinepubs/009695399/functions/stdin.html
现在假设我有一组需要第4个进程的进程。例如,使用fork()
exec()
创建的子进程需要在socketpair()
之前使用fork()
创建的控件套接字的句柄。对于此示例,第四个句柄(套接字)的目的是在父进程和子进程之间提供链接。现在问题来了......孩子怎么知道哪个FD是控制插座?只要#define CONTROL_SOCKET 3
和dup2(new_socket,CONTROL_SOCKET)
之间的fork()
,我就无法使用静态数字(例如:exec()
)。我能够foo = write(CONTROL_SOCKET, bar, baz)
在孩子的内心。让我们把它看作任何其他FDs
打开我的应用程序预计将关闭exec所以我的逻辑是dup2()
不会关闭任何不会被关闭的任何东西exec()
{1}}。
我知道有几种可能的解决办法可以避免这样做(例如:在环境变量或程序参数中传递FD),网上有很多例子说明如何这样做。我不明白的是正在解决的问题是什么?静态定义FD的问题是什么?乍一看,这是一种避免不存在问题的感觉。有些系统使用0,1和2以外的FD,我可能会在执行前覆盖dup2(<some fd>,3)
的重要内容吗?
注意: 这个问题实际上是一个关于编写可在现有 POSIX操作系统之间移植的代码的问题。
答案 0 :(得分:2)
除了0,1,2之外,没有广泛使用的文件描述符。我似乎记得一些使用固定文件描述符超出该范围的跟踪系统(虽然通常不是3),但它们非常例外(我不记得在这个千年里注意到了它。)
总的来说,如果集合中的第一个进程能够确保描述符在启动时未被使用,则可以安全地将描述符传递给其子进程。如果您发现描述符已在使用中,则可以向控件套接字打开不同的描述符,然后使用fstat()
来比较两个描述符。如果它们是同一个设备,你可以继续使用继承的描述符3;如果没有,您需要dup2()
和close()
控制套接字。
如果您的进程计划只是自己打开控件套接字,则不必担心使用哪个文件描述符。
答案 1 :(得分:1)
您可能不希望这样做的原因是,与0
,1
和2
不同,您无法保证3
将成为dup2(<some fd>, 3)
打开,除非你总是控制进程的启动方式。
但是,为某个频道设置固定的描述符号并没有错。
绝对不会用<some fd>
覆盖任何内容。
它只会为您的流程及其子项掩盖reduce
,但3在父流程中根本不会受到影响。
答案 2 :(得分:-1)
你不需要这么复杂。
即。不要将dup2()
与您不确定的目标描述符一起使用(例如,因为您刚关闭它),或者您不希望隐式关闭它。
只需在命令行或环境变量中传递new_socket
本身,作为表示其整数值的字符串,如注释中所示。
请参阅此答案:https://stackoverflow.com/a/21596854/816536但忽略“P1.c”的第二个变体 - 这是失败的方式。