STDIN_FILENO 和 STDOUT_FILENO 在 c 中是只读的吗?
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() 使 newfd 成为 oldfd 的副本,如有必要,首先关闭 newfd。
:
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
?
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
tells me that dup2() makes newfd be the copy of oldfd, closing newfd first if necessary.
:
int dup2(int oldfd, int newfd);
But aren't STDIN_FILENO
and STDOUT_FILENO
read only?
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>
Or dup2
didn't change newfd
at all?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
常量本身(在 POSIX 上,
STDIN_FILENO
为0
且STDOUT_FILENO
为1
)确实是只读的,但是它们所描述的文件描述符可能会被关闭,并在其位置上打开其他东西;它们只是普通的文件描述符(通常设置一个标志,以便它们在execve()
系统调用时保持打开状态)。正在改变的是驻留在操作系统内核中的进程的文件描述符表。看到那个
syscall
指令了吗?这在这里非常重要;这就是你的进程进入操作系统的陷阱。The constants themselves (on POSIX,
STDIN_FILENO
is0
andSTDOUT_FILENO
is1
) are indeed read-only, but the file descriptors they characterize may be closed and something else opened in their place; they're just ordinary file descriptors (usually with a flag set so that they stay open on anexecve()
system call).The thing that is changing is the table of file descriptors for the process that resides inside the OS kernel. See that
syscall
instruction? That's really important here; that's the trap out of your process into the OS.这是守护进程的最后一部分,涉及将
stdout
和stdin
重定向到/dev/null
,因为稍后不会使用它们。守护进程通常写入日志文件,而不是标准输出。
引用这篇文章:
This is the final part of daemonizing and involves redirecting
stdout
andstdin
to/dev/null
because they are not going to be used later.Daemons normally write to log files, not to the standard output.
Citing this article:
关闭 stdin 和 stdout 效果很好。尽管当您这样做时,您无法再读取它们,并且必须使用 dup() 描述符。
Closing stdin and stdout works perfectly fine. Although when you do this you cannot read from them anymore and have to use the dup()'d descriptors.