我遇到了一个我希望帮助理解的场景。示例代码如下。
fclose(stdin);
fclose(stdout);
fclose(stderr);
int sockets[2];
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0);
int socketA = sockets[0];
int socketB = sockets[1];
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == 0);
int socketC = sockets[0];
int socketD = sockets[1];
assert(socketA == 0);
assert(socketB == 1);
assert(socketC == 2);
assert(socketD == 3);
unblock_socket(socketA);
unblock_socket(socketB);
unblock_socket(socketC);
unblock_socket(socketD);
unsigned char buffer = 0;
assert(::recv(socketA, &buffer, sizeof(buffer), 0) == -1);
assert(::recv(socketC, &buffer, sizeof(buffer), 0) == -1);
assert(::recv(socketB, &buffer, sizeof(buffer), 0) == -1);
assert(::recv(socketD, &buffer, sizeof(buffer), 0) == -1);
pid_t pid = fork();
if (pid == -1)
assertfalse;
else if (pid > 0)
{
int status = 0;
waitpid(pid, &status, 0);
}
else
{
assert(execv("/usr/sbin/chown", nullptr) == 0) // Prints "usage: chown [-fhv] [-R [-H | -L | -P]]..." to stderr
_exit(EXIT_FAILURE);
}
assert(::recv(socketA, &buffer, sizeof(buffer), 0) == -1);
assert(::recv(socketC, &buffer, sizeof(buffer), 0) == -1);
assert(::recv(socketB, &buffer, sizeof(buffer), 0) == -1);
assert(::recv(socketD, &buffer, sizeof(buffer), 0) == -1); // Assertion failed!. Reading from socket D we see "usage: chown [-fhv] [-R [-H | -L | -P]]..."
我已经关闭了stderr(文件描述符2)并随后打开了套接字C,它接受了现在可用的文件描述符2.然而,chown仍然似乎设法将其错误输出写入文件描述符2.应该chown没有实现stderr被关闭并且文件描述符2重新分配,因此不写入它?
由于
答案 0 :(得分:0)
这完全符合预期。
关闭stderr,然后调用socketpair()。 SocketC == 2(即现在的stderr)。
chown()继承了这些文件描述符,因此当它写入stderr时,它真正写入SocketC,父级从SocketD读取。
答案 1 :(得分:0)
已解决 - 我应该将stdin / stdout / stderr重定向到/ dev / null,这样就不会重新分配文件描述符0-2。这是一个守护进程应用程序。
但是我仍然发现奇怪的chown是打印到文件描述符2.在我看来,使用
打印dprintf(STDOUT_FILEERR, "usage: chown [-fhv] [-R [-H | -L | -P]]...");
或者
const char error[] = "usage: chown [-fhv] [-R [-H | -L | -P]]...";
write(STDOUT_FILENO, error, sizeof(error) - 1);
而不是
fprintf(stderr, "usage: chown [-fhv] [-R [-H | -L | -P]]...");
或类似的东西......就像在第一个例子中dprintf写入socketC(文件描述符2)而导致问题但在第二个例子中fprintf实现了stderr FILE *对象被关闭而不进行写入。
非常感谢任何进一步的见解。