2
fd = open("/dev/null", O_RDWR);
if (fd == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                  "open(\"/dev/null\") failed");
    return NGX_ERROR;
}

if (dup2(fd, STDIN_FILENO) == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
    return NGX_ERROR;
}

if (dup2(fd, STDOUT_FILENO) == -1) {
    ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
    return NGX_ERROR;
}


if (fd > STDERR_FILENO) {
    if (close(fd) == -1) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
        return NGX_ERROR;
    }
}

man告诉我dup2() makes newfd be the copy of oldfd, closing newfd first if necessary.

int dup2(int oldfd, int newfd);

但不是只读STDIN_FILENO的吗?STDOUT_FILENO

Dump of assembler code for function dup2:
0x00000037aa4c6ac0 <dup2+0>:    mov    $0x21,%eax
0x00000037aa4c6ac5 <dup2+5>:    syscall 
0x00000037aa4c6ac7 <dup2+7>:    cmp    $0xfffffffffffff001,%rax
0x00000037aa4c6acd <dup2+13>:   jae    0x37aa4c6ad0 <dup2+16>
0x00000037aa4c6acf <dup2+15>:   retq   
0x00000037aa4c6ad0 <dup2+16>:   mov    0x28a4d1(%rip),%rcx        # 0x37aa750fa8 <free+3356736>
0x00000037aa4c6ad7 <dup2+23>:   xor    %edx,%edx
0x00000037aa4c6ad9 <dup2+25>:   sub    %rax,%rdx
0x00000037aa4c6adc <dup2+28>:   mov    %edx,%fs:(%rcx)
0x00000037aa4c6adf <dup2+31>:   or     $0xffffffffffffffff,%rax
0x00000037aa4c6ae3 <dup2+35>:   jmp    0x37aa4c6acf <dup2+15>

还是dup2根本没有改变newfd

4

3 回答 3

4

常量本身(在 POSIX 上STDIN_FILENO是 is0STDOUT_FILENOis 1)确实是只读的,但是它们表征的文件描述符可能是关闭的,并且在它们的位置打开了其他东西;它们只是普通的文件描述符(通常设置一个标志,以便它们在execve()系统调用时保持打开状态)。

正在改变的是驻留在操作系统内核中的进程的文件描述符表。看到那个syscall指令了吗?这在这里非常重要;这就是你的进程进入操作系统的陷阱。

于 2011-06-01T07:59:57.153 回答
3

这是守护进程的最后一部分,涉及重定向stdoutstdin到,/dev/null因为它们以后不会使用。

守护进程通常写入日志文件,而不是标准输出。

引用这篇文章

一旦它运行,一个守护进程就不应读取或写入启动它的终端。确保这一点最简单和最有效的方法是关闭与 stdin、stdout 和 stderr 对应的文件描述符。然后应该将它们重新打开到 /dev/null,或者如果喜欢到其他位置。不关闭它们有两个原因:

  • 防止引用这些文件描述符的代码失败,并且
  • 以防止描述符被重用于其他目的。
于 2011-06-01T07:57:53.673 回答
0

关闭标准输入和标准输出工作得很好。虽然当你这样做时,你不能再从它们中读取数据并且必须使用 dup()'d 描述符。

于 2011-06-01T07:59:16.097 回答