问题描述
|
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,\"dup2(STDIN) failed\");
return NGX_ERROR;
}
if (dup2(fd,STDOUT_FILENO) == -1) {
ngx_log_error(NGX_LOG_EMERG,\"dup2(STDOUT) failed\");
return NGX_ERROR;
}
if (fd > STDERR_FILENO) {
if (close(fd) == -1) {
ngx_log_error(NGX_LOG_EMERG,\"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
?
解决方法
常量本身(在POSIX上,
STDIN_FILENO
为0
,STDOUT_FILENO
为1
)确实是只读的,但它们所表征的文件描述符可能已关闭,而其他位置已打开。它们只是普通的文件描述符(通常设置一个标志,以便它们在execve()
系统调用中保持打开状态)。
变化的是位于OS内核内部的进程的文件描述符表。看到那个“ 14”指令?这真的很重要;这是您进入操作系统的过程的陷阱。
, 这是守护进程的最后一部分,涉及到将stdout
和stdin
重定向到/dev/null
,因为以后将不再使用它们。
守护程序通常写入日志文件,而不是标准输出。
引用本文:
守护程序一旦运行,就不应从其启动的终端中读取或写入。确保这一点的最简单,最有效的方法是关闭与stdin,stdout和stderr对应的文件描述符。然后应重新打开这些文件,或者将其打开到/ dev / null,或者如果需要,可以将其重新打开。没有关闭它们有两个原因:
为了防止引用这些文件描述符的代码失败,并且
以防止描述符再用于其他目的。
, 关闭stdin和stdout可以很好地工作。尽管执行此操作时无法再从它们中读取内容,而必须使用dup()\ d描述符。