создание и обмен процессами fork (), pipe () и exec () - PullRequest
5 голосов
/ 23 февраля 2011

Мне нужно написать программу, которая создает процесс, используя pipe().

Моя первая задача - написать родительский процесс, который генерирует четыре дочерних процесса, используя функцию fork().

После успешного выполнения fork() замените дочерний процесс другим процессом rover1, rover2, rover3, and rover4, хотя все они имеют одинаковый код.

Функция процессов заключается в следующем.

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

    mynumber = (3 * mynumber + 4 * numberreceived)/7

  2. Этот процесс продолжается до тех пор, пока родитель не отправит сообщение о том, что система стабильна. Родитель также имеет свой начальный номер. Он получает номера всех детей и вычисляет новый номер следующим образом:

    mynumber = (3 * mynumber + <em>numbers sent by all the children</em>)/7

  3. Родитель отправит этот номер всем своим детям. Этот процесс будет продолжаться, пока родитель не обнаружит, что его номер больше не меняется. Тогда он скажет детям, что система стала стабильной.

Это то, что я сделал, но мой профессор сказал, что я должен использовать exec () для выполнения дочернего процесса и заменить дочерний процесс другим дочерним процессом. Я не уверен, как использовать exec (). Не могли бы вы помочь мне с этим.

Я прикрепляю только первое дочернее поколение.

// I included stdio.h, unistd.h stdlib.h and errno.h 
int main(void)
{
  // Values returned from the four fork() calls
  pid_t rover1, rover2, rover3, rover4;

  int parentnumber, mynumber1, mynumber2, mynumber3, mynumber4;

  int childownnumber1 = 0, status = 1, childownnumber2 = 0,
      childownnumber3 = 0, childownnumber4 = 0, numberreceived = 0;

  printf("Enter parent number: ");
  printf("%d", parentnumber);
  printf("Enter each children number");
  printf("%d %d %d %d", mynumber1, mynumber2, mynumber3, mynumber4);

  // Create pipes for communication between child and parent
  int p1[2], p2[2];
  // Attempt to open pipe
  if (pipe(p1) == -1) {
    perror("pipe call error");
    exit(1);
  }
  // Attempt to open pipe
  if (pipe(p2) == -1) {
    perror("pipe call error");
    exit(1);
  }

  // Parent process generates 4 child processes
  rover1 = fork();

  // if fork() returns 0, we're in the child process;
  // call exec() for each child to replace itself with another process
  if (rover1 == 0) {
    for(; numberreceived != 1; ) {  
      close(p1[1]); // Close write end of pipe
      close(p2[0]); // Close read end of second pipe

      // Read parent's number from pipe
      read(p1[0], &numberreceived, sizeof(int));

      if (numberreceived == 1) {
        // System stable, end child process
        close(p1[0]);
        close(p2[1]);
        _exit(0); // End child process
      }

      mynumber1 = (int)((3*mynumber1 + 4*numberreceived)/7.0);

      printf("\nrover1 number: ");
      printf("%i", mynumber1);

      // Write to pipe
      write(p2[1], &mynumber1, sizeof(int));    
    }       
  }
  /* Error:
   * If fork() returns a negative number, an error happened;
   * output error message
   */
  if (rover1 < 0) {
    fprintf(stderr,
            "can't fork, child process 1 not created, error %d\n",
            errno);
    exit(EXIT_FAILURE);
  }
}

Ответы [ 2 ]

2 голосов
/ 23 февраля 2011

Семейство функций exec используется для замены текущего процесса новым процессом. Обратите внимание на использование слова replace . После вызова exec текущий процесс исчезает и начинается новый процесс. Если вы хотите создать отдельный процесс, вы должны сначала fork, а затем exec новый двоичный файл в дочернем процессе.

Использование функций exec похоже на выполнение программы из командной строки. Программа для выполнения, а также аргументы, переданные программе, предоставляются в вызове функции exec.

Например, следующая exec команда * эквивалентна следующей команде оболочки:

execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);

/bin/ls -r -t -l

* Обратите внимание, что "arg0" - это имя команды / файла для выполнения


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

Следующие ссылки должны помочь вам начать работу:

1 голос
/ 23 февраля 2011

Если вы предполагаете использовать exec, то вам следует разбить вашу программу на два двоичных файла.

По сути, код, который теперь исполняется дочерним элементом, должен находиться во втором двоичном файле и вызываться с помощью exec.

Перед вызовом одной из функций семейства exec,вам также нужно перенаправить дескрипторы канала на стандартный ввод / вывод нового процесса, используя dup2.Таким образом, код во втором двоичном файле, который получает exec, не будет знать о канале и будет просто читать / записывать на стандартный ввод / вывод.

Стоит также отметить, что некоторые изданные, которые вы сейчас используете в дочернем процессе, наследуются от родительского элемента через fork.При использовании exec дочерний элемент не будет передавать ни данные, ни код родительского элемента, поэтому, возможно, вы также можете рассмотреть возможность передачи необходимых данных через канал.

...