Дочерний процесс не завершается с помощью fork () - PullRequest
0 голосов
/ 25 февраля 2019

Я создаю простую командную оболочку Linux на C. У меня проблемы с пониманием, где у моего кода возникают проблемы.«команды» - это список строк команд Linux, которые я хочу выполнять одновременно как дочерние процессы одного из родителей.Когда все будет выполнено, я хочу, чтобы родитель вышел из функции.Однако когда я вызываю exit (0), цикл for продолжается и снова анализирует текущую команду, вызывая повторное выполнение аргументов в execvp.Я правильно использую fork () и wait ()?Я попытался использовать waitpid (), но безуспешно.

void executeShell(char** commands){
    char **arr = commands;
    char *c;
    pid_t pid, wpid;
    int status = 0;

    for (c = *arr; c; c=*++arr){
        // printf("%d-\n", strcmp(command, "exit"));

        if (strcmp(c, "exit") == 0){
            EXIT = 1;
            return;
        }

        printf("Running command \'%s\'...\n", c);

        char** args = parseStringToTokenArray(c, " ");
        free(args);

        /* fork and execute the command */
        pid = fork();
        if(pid < 0){
            perror("fork() error\n");
            return;
        }
        /* child process executes command */
        else if (pid == 0){
            /* 'cd' is not a part of /bin library so handle it manually */
            if (strcmp(args[0], "cd") == 0){
                changeDirectory(args[1]);
            }
            else if (strcmp(args[0], "sdir") == 0){
                searchDirectory(args[1]);
            }else{
                /* parse commands with arguments */
                execvp(args[0], args);//execute the command
            }
            exit(0);// <-----command is finished, so why no exit?
        }                                     
    }                                          
    /* wait for children to complete */          
    while((wpid = wait(&status)) > 0);         
}                                               

1 Ответ

0 голосов
/ 25 февраля 2019

Если execvp завершается успешно, все адресное пространство дочернего процесса заменяется программой, вызванной execvp().Это означает, что exit(0) будет вызываться только после двух ваших особых случаев, то есть cd и sdir.Что касается вашего кода, то execvp() никогда не должен возвращаться, если только нет ошибки.

Еще одна проблема заключается в том, что вы освобождаете args сразу после его выделения, а затем продолжаете использовать его у своего ребенка.процессы.Это неопределенное поведение.

Единственная проблема, которую я вижу с вашим кодом wait, заключается в том, что, если какой-либо из дочерних элементов блокирует ожидание пользовательского ввода, родительский блок блокирует ожидание выхода дочернего элемента.

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

...