How It Works
Toggle navigation
How It Works
Home
About Me
Archives
Tags
dup2小析
linux
2016-02-16 08:55:30
440
0
0
ochapman
linux
经常阅读后台程序源码的话,会看到在初始化时dup2相关的函数,例如nginx的 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 0 if (dup2(fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); return NGX_ERROR; } #endif if (fd > STDERR_FILENO) { if (close(fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed"); return NGX_ERROR; } } return NGX_OK; # dup2到底做了什么 dup2的定义 int dup2(int oldfd, int newfd); 从内核代码fs/file.c,实际在`SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)`函数 从current上取出files_struct struct files_struct *files = current->files; 从oldfd取出struct file file = fcheck(oldfd); 再调用`do_dup2`函数 再从files_struct取出fdtable, fdt = files_fdtable(files); 将oldfd的struct file赋值给newfd的file上 rcu_assign_pointer(fdt->fd[fd], file) 当然,并不是简单地复制,还需要对O_CLOEXEC进行清除,即dup2的newfd和oldfd并没有共享O_CLOEXEC标志 __clear_close_on_exec(fd, fdt); 一句话,简单地改变了newfd映射的file结构,达到操作到newfd时,实际上还是写到oldfd的之前映射的file上。 #为何需要这样做 有时候,在终端运行一些命令,这些命令在后台运行后,会在屏幕上时不时地打印一些莫名其妙日志。这是因为没有妥善处理好标准输出/错误。导致后来写标准输出或错误(如引用了第三方的库,这些库输出到标准输出/错误),此时都输出到终端屏幕上。因此,需要在初始化时,先处理好标准输出/错误文件描述符,让后面操作这些操作符的地方,都能正确写到我们想写的地方去。 例如,一个后台进程希望所有写到标准输出的地方,都写到/dev/null(或者在有写到日志的需求,将打印写到指定的日志文件)上。 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <stdlib.h> int main(int argc, char **argv) { int fd = open("/dev/null", O_RDWR); if (fd == -1) { fprintf(stderr, "open() failed %d\n", errno); exit(-1); } printf("i'm here 1\n"); if (dup2(fd, STDOUT_FILENO) == -1) { fprintf(stderr, "dup2() stdout return -1"); exit(-1); } printf("i'm here 2\n"); if (dup2(fd, STDIN_FILENO) == -1 ) { fprintf(stderr, "dup2() stdout return -1"); exit(-1); } printf("i'm here 3\n"); close(fd); //do something }
Pre:
pam简单例子
Next:
了解新事物
0
likes
440
Weibo
Wechat
Tencent Weibo
QQ Zone
RenRen
Table of content