При создании dd (из gnu coreutils) я обнаружил кое-что, что меня удивило:
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 для изменения файлового дескриптора на файловые дескрипторы0 (stdin) и 1 (stdout).
Я посмотрел код , чтобы увидеть, если это сделано с помощью оптимизации человека или компилятора, и это действительно так:
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));
}
В следующем коде они используют STDIN_FILENO (и STDOUT_FILENO) независимо от того, сказано ли dd читать из stdin или из файла.Но того же можно было бы достичь, просто сохранив fd в некоторой переменной и используя это.Использование 2 дополнительных системных вызовов и набора кода только для сохранения 1 int кажется нецелесообразным.Так в чем же польза или повторное использование файлов stdin / stdout?