在从nu追踪dd时,我发现了一些令我惊讶的东西:
openat(AT_FDCWD, "/dev/zero", O_RDONLY) = 3
dup2(3, 0) = 0
close(3) = 0
lseek(0, 0, SEEK_CUR) = 0
openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
dup2(3, 1) = 1
close(3) = 0
mmap(NULL, 1060864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x681e58939000
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
close(0) = 0
close(1) = 0
dd打开应该读取/写入的文件,然后使用dup2将filedescriptor更改为filedescriptor 0(stdin)和1(stdout)。
我抬起code,看看这是通过人工优化还是通过编译器优化完成的,并且确实存在:
static int
ifd_reopen (int desired_fd, char const *file, int flag, mode_t mode)
{
int ret;
do
{
process_signals ();
ret = fd_reopen (desired_fd, file, flag, mode);
}
while (ret < 0 && errno == EINTR);
return ret;
}
// ...
if (input_file == NULL)
{
input_file = _("standard input");
set_fd_flags (STDIN_FILENO, input_flags, input_file);
}
else
{
if (ifd_reopen (STDIN_FILENO, input_file, O_RDONLY | input_flags, 0) < 0)
die (EXIT_FAILURE, errno, _("failed to open %s"),
quoteaf (input_file));
}
在以下代码中,无论是否告诉dd从stdin或文件中读取,它们都使用STDIN_FILENO(和STDOUT_FILENO)。但是,只要将fd存储在某个变量中并使用它,就可以实现相同的目的。使用2个额外的syscall和一堆代码来保存1个int似乎是不合理的。那么或重用stdin / stdout的fd有什么好处?