Дочерний процесс берет на себя родительский процесс при запуске fork () - PullRequest
0 голосов
/ 15 октября 2019

У меня проблема, когда я пытаюсь запустить несколько команд через execvp (). Для этого у меня есть цикл while, выполняющий каждую команду, анализирующий ее, затем вызывающий функцию для использования fork + exec.

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

Как запустить процесс в дочернем процессе, носохранить контроль над родителем? Все примеры, которые я видел на SO, были для родительских процессов, которые ожидают завершения дочернего процесса, прежде чем продолжить, но у меня нет выбора в этом назначении - я должен оставить дочерние процессы запущенными и проверить позже. чтобы увидеть, работают ли они по-прежнему.

Вот некоторый псевдокод моего мыслительного процесса:

funct forkprocess() {
   //call fork
   //call execvp within child process, let process run and return control to parent
       //if execvp failed, kill child process
   //return child pid
}

int main() {
   while(not end of file containing list of commands) :
      //parse command for execvp call
      //call forkprocess() to run process
      //if childpid is returned, report it and store pid
      //else, report failure
   }
}

Мой вывод был близок к следующему:

\\parent PID is printed
\\any code outside the if-else ladder for fork is printed
\\it jumps back to main and prints any statements there

[jumps to next iteration in loop, ie. the next command]

\\child PID is printed
\\parent PID is printed
\\any code outside the if-else ladder for fork is printed
\\it jumps back to main and prints any statements there
\\child PID is printed

Ответы [ 2 ]

0 голосов
/ 18 октября 2019
int main(int argc, char ** argv) {
    int status;

    if((waitpid(fork(), &status, 0)) == -1) {
       execvp(...);
       /* print error */
       exit(1);
    }
    return 0;
}

Спасибо за вопрос: если fork передается прямо в waitpid, родитель будет ждать, в то время как дочерний процесс выполнит exec, который выйдет из потока в случае успеха или вернется в случае ошибки и продолжит печатать ошибку и завершать работу. Это действительно полезно для одновременного выполнения нескольких функций ...

int main(int argc, char ** argv) {
    int *status = malloc(sizeof(int) * (argc - 1));
    int i = 0;

    while(((waitpid(fork(), &status[i++], 0)) == -1) || i < argc) {
       execvp(argv[i], &argv[i + 1]);
       /* print error */
       exit(1);
    }
    return 0;
}
0 голосов
/ 15 октября 2019

Вы должны убедиться, что exec вызывается только у потомка, а не у родителя. Когда fork() возвращается, он делает это дважды (один раз в дочернем, один раз в родительском) и возвращает следующие значения :

  • ненулевые (PIDребенка), если мы находимся в родителя. Мы можем использовать этот PID для ожидания завершения дочернего процесса, используя waitpid.
  • ноль, если мы находимся в дочернем. в этом случае он возвращается только один раз в родительском процессе, поскольку дочерний процесс не может быть создан)

Возможно, вы захотите рассмотреть возможность использования следующей структуры:

int pid = fork();
if(pid < 0) {
    perror("fork"); // remember to error check!
} else if (pid == 0) {
    // We are in the child
    // ...
    if(execvp(...) < 0) {
        perror("exec");
    }
} else {
    // We are in the parent; wait for the child to terminate using waitpid if desired.
    waitpid(...);
}

Iвключите waitpid вызов здесь для простоты;поскольку ваше назначение требует, чтобы вы продолжали работать дочерние процессы, вы можете проверить их состояние позже, используя либо эту функцию, либо обработав SIGCHLD.

...