守护进程:关闭 stderr 和 accept(2)

daemon: closed stderr and accept(2)

我编写了一个 TCP 守护程序,它接受给定端口上的客户端连接,然后使用 execv(3) 执行命令。在每个编写守护进程的教程中,都提到关闭 stdin、stdout、stderr 以成功守护进程。

但是我发现 accept(2) 重用了已经关闭的文件描述符编号 stdout/stderr 所以在调用 fork(2) 和 execv(3) 之后,子进程将输出写入套接字只是因为 stdout/stderr 映射到现在与客户端套接字关联的文件描述符。

有什么想法可以在不诉诸 shell 输出重定向的情况下避免这种情况吗?

首先,对于守护进程,它的父进程必须退出,所以它会被重定向到 INIT 进程,它将成为一个守护进程。

我认为你的用例是,你从其他客户端获取命令并在你的守护进程中执行它,然后将输出重定向到请求客户端。 如果您打算使用关闭 STD_ERR 和 STD_OUT 概念,那么您必须 小心 仅以串行方式接收请求。

现在来谈谈你的问题, 要将 STD_ERR 和 STD_OUT 重定向到已接受的客户端 FD,您必须保持 STD_ERR 和 STD_OUT 打开直到客户端被接受,仅接受客户端后,关闭 STD_OUT 然后将 DUP 与接受的客户端 FD 一起使用。

参考下面 link 以从此类问题中获得更多想法。 practical examples use dup or dup2

各位!

如果您不希望标准 input/output 的文件描述符被 accept(2) 和可能 returns 新文件描述符的任何其他函数重用,请避免调用 close(2) /fclose(3),但将它们重定向到 /dev/null(如果可用)。这个想法来自 daemon(3) 的手册页。

freopen ("/dev/null", "r", stdin);
freopen ("/dev/null", "w", stdout);
freopen ("/dev/null", "w", stderr);