Создание дочернего процесса в системах Unix?

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

Как мне написать родительский процесс?

Спасибо.

Вот код дочернего процесса:

#include <stdio.h>

int main(void) {
  while(1) {
    printf("*");
    sleep(1);
  }
}

А вот и родительский процесс:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(void) {
  if (fork()) {
    while(1) {
      printf("-\n");
      sleep(5);
    }
  } else {
    execl("./", "dummy", (char *)0);
  }
}

person Hakan Svensson    schedule 27.03.2010    source источник
comment
Вы говорите, что потерпели неудачу, но не показали никакого кода. Как вы ожидаете, что мы скажем, где вы делаете неправильно? Кроме того, родительский процесс управляет дочерним процессом, поэтому дочерний процесс ВСЕГДА завершается ДО родительского процесса. Если родительский процесс умирает первым, прародитель принимает дочерний процесс (вплоть до /sbin/init, прапрародитель всех процессов, который никогда не должен умирать).   -  person Juliano    schedule 28.03.2010
comment
Хорошо, извините, я отредактировал свой вопрос с кодом.   -  person Hakan Svensson    schedule 28.03.2010
comment
Добавьте perror(execl) после оператора execl и посмотрите, что произойдет.   -  person Duck    schedule 28.03.2010


Ответы (3)


Системный вызов fork() может возвращать три разных состояния: сбой (‹0), родительский процесс (>0) или дочерний процесс (==0). Вы должны правильно протестировать возвращаемое значение.

int pid = fork();

if (pid < 0) {
  /* handle error */
  perror("fork");
  exit(1);
} else if (pid > 0) {
  /* parent code */
} else {
  /* child code */
}

Ваш системный вызов execl() неверен. Первый аргумент - это путь к программе, которую вы хотите выполнить, "./" недействителен, это должно быть как минимум что-то вроде "./dummy". Следующим аргументом по соглашению является имя команды (argv[0] в исполняемой программе), которое может быть повторением первого аргумента. Так:

execl("./dummy", "dummy", NULL);

Также обратите внимание, что оператор printf("*") в дочерней программе, вероятно, будет буферизоваться, и вы ничего не увидите на терминале. Вы должны либо добавить "\n" в конец, либо вызвать fflush(stdout), чтобы сбросить стандартный вывод.

person Juliano    schedule 27.03.2010
comment
Спасибо за ваш ответ, он мне очень помог. - person Hakan Svensson; 28.03.2010

Основное использование fork в C

int PID = fork();

if( PID < 0 ) {
    //fail
    return PID;
}
else if( !PID ) {
    //child process
    return exec( prog, args );
} 
else {
    //parent process
    return 0;
}
person zellio    schedule 27.03.2010
comment
Да, родительский процесс БУДЕТ завершен, даже если некоторые из его потомков/потомков все еще живы. Если родитель хочет их дождаться, он должен делать это намеренно. - person MarkR; 28.03.2010

Невозможно заставить дочерний процесс «не завершаться», когда он будет завершен (вы все равно сможете в родительском процессе wait получить информацию о том, как он завершился, но это все). Кроме того, любой из многих примеров fork/exec в Интернете, таких как этот, должен работать - почему бы вам не попробовать и посмотреть, работает ли он так, как вы хотите (в этом случае вам просто нужно изменить то, что вы делали по-другому, в вашей собственной попытке). Если это не работает должным образом (за исключением невозможности в первом предложении в этом A;-), пожалуйста, отредактируйте свой, чтобы добавить подробные сведения о том, как код ведет себя не так, как вы ожидаете.

person Alex Martelli    schedule 27.03.2010
comment
Вы можете поместить цикл в дочерний процесс после того, как он завершит свою работу, но до выхода, который ожидает смерти родителя (например, ожидая EOF на канале, подключенном к родителю). - person caf; 28.03.2010
comment
Если вы контролируете исходный код дочернего процесса, никогда не имеете в нем ошибок, и каким-то образом можете гарантировать, что он не получит нежелательных сигналов, да, но это может быть довольно трудно гарантировать. - person Alex Martelli; 28.03.2010