Почему GNU dd повторно использует файловые дескрипторы 0 и 1 с dup2? - PullRequest
0 голосов
/ 07 октября 2018

При создании 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?

...