Nano Hash - криптовалюты, майнинг, программирование

Выход трубопровода на вилки в C

У меня есть несколько процессов в программах, и я хочу последовательно передавать вывод из одного процесса в другой. Я считаю, что я уже связал стандартный ввод процесса с концом чтения предыдущего процесса и связал стандартный вывод с концом записи канала. Я все еще не вижу выхода. Я что-то пропустил со ссылками здесь?

  int pipeFds[numProg][2];
  
  for (int i = 0; i < numProg; i++) {
    if (pipe(pipeFds[i]) != 0) { // create pipe for each process
      printf("Failed to create pipe!");
      exit(1);
    }
    child_pid = fork();
    if (child_pid == -1) {
      printf("Error while creating fork!");
      exit(1);
    } 
    if (child_pid == 0) {
      if (i == 0) { 
        close(pipeFds[i][READ_END]); // close STDIN first process since it does not read
      } else { 
        // change stdin to read end of pipe for intermediary processes
        close(pipeFds[i]);
        dup2(pipeFds[i - 1][READ_END], STDIN_FILENO);
      }
      dup2(pipeFds[i][WRITE_END], STDOUT_FILENO); // change stdout to write end of pipe
      execvp(progs[i][0], (char *const * )progs[i]);
    } else {
      // parent process stuff
    }
  }
  
  // Close pipes except last pipe for EOF
  for (int i = 0; i < numProg - 1; i++) {
    close(pipeFds[i][READ_END]);
    close(pipeFds[i][WRITE_END]);
  }

22.09.2020

Ответы:


1

Помните, что вам нужно закрыть все каналы в каждом процессе, чтобы он работал.

Пример:

Если numProg=2 вы создаете 2 канала и 2 дочерних процесса. При добавлении родителя запущено 3 процесса, и в каждом из них в итоге нужно закрыть все пайпы.

Для child_pid==0 вы закрываете [READ_END], но никогда не закрываете [WRITE_END].

Для child_pid==1 вы делаете close(pipeFds[1]). Вам нужно указать [READ_END] и [WRITE_END].

Затем каждый дочерний процесс завершается через execvp, который, однако, может вернуть управление в случае сбоя. На справочной странице:

Семейство функций exec() заменяет текущий образ процесса новым образом процесса. .. Функции exec() возвращают значение только в случае возникновения ошибки.

Таким образом, вы можете добавить _exit(0); после execvp, чтобы гарантировать правильное завершение каждого дочернего процесса даже в случае сбоя execvp.

Родительский процесс закрывает все каналы, кроме последнего. Итак, в примере NumProg=2, [READ_END] и [WRITE_END] из pipeFd[1] оба никогда не закрываются.

Наконец, родительский процесс должен wait закрыть все дочерние процессы (используя while(wait(NULL) != -1);), в противном случае вы можете получить зомби-процессы или процессы-сироты.

26.09.2020

2
  1. ваш код содержит случайный close(pipeFds[i]);

  2. вы должны закрыть трубы внутри // parent process stuff. С вашим кодом каждый дочерний элемент сохраняет открытыми pipeFds предыдущих дочерних элементов. Например.

     } else {
         // parent process stuff
         if (i > 0)
             close(pipeFds[i - 1][READ_END]);
         close(pipeFds[i - 1][READ_END]);
     }
    
  3. может быть более эффективно иметь одну пару fds[2] вместо numProg.

22.09.2020
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..