C, Fork (), принять аргумент CL и выполнить CHDIR - PullRequest
0 голосов
/ 06 ноября 2018
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
char *getcwd(char *buf, size_t size); //define getcwd
char PATH_MAX[1024]; //define max size of path


int chdir(const char *path);


int main(int argc, char *argv[]) { // gets arguments when program ran, no arguments means argv=1

    pid_t pid; //process ID = pid
    pid=fork();
    char cwd[1024]; //compare directory to max character size

   if(pid==0){ //child has been forked! //child process created
    int ret;
    printf("Child PID=%d\n", getpid());
    getcwd(PATH_MAX, sizeof(PATH_MAX));
    printf(" My current working directory is: %s\n", PATH_MAX);

    ret= execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);
    printf("%d\n", ret); //why isn't this printed out?
   }

    //} 
   else {
    int status;
        //parent process
        //wait for child to complete
        printf("Parent PID=%d\n", getpid());
        if (waitpid(pid, &status, 0) == -1) {
            printf("ERROR");
        }
        else {
        printf("Child done.\n");
        getcwd(PATH_MAX, sizeof(PATH_MAX));

        printf("0");
        exit(0);
    }
}
}

Я оставил закомментированный код, чтобы вы могли увидеть мой мыслительный процесс. Если я правильно понимаю, оболочка (терминал) - это собственный процесс, поэтому, когда вы вызываете fork, он создает новый дочерний процесс, а его родитель становится оболочкой. Поэтому попытка chdir в дочернем процессе не будет преобразована в оболочку, и вы останетесь в том же каталоге, поэтому вам нужно будет выполнить функцию chdir в родительском PID, который теперь является оболочкой, да?

Я с трудом пытаюсь выяснить, куда именно я должен поместить эту команду chdir() и какую разновидность exec мне нужно использовать для выполнения команд терминала.

Я тестирую 3 разные команды в качестве аргументов командной строки при запуске в терминале. Это после создания файла с gcc -o script script.c

$ ./script 
 result - print out current directory
 print out "Usage: "<dir>" string. no command executed

$ ./script . 

result -"Executing ls . --all -l --human-readable" string

  executes above commands 

$./script / 

result - should execute above commands but change directory before 

executing

$./script /blah/blah

result - can't execute chdir

exit status: 1

Я полагаю, что этот код должен заставить дочерний процесс вернуть -1, который завершит его, или, если мой оператор if верен, он выведет сообщение об ошибке.

Буду признателен за любую помощь, я полагаю, что я понял логику или, по крайней мере, немного. Просто трудно реализовать chdir.

1 Ответ

0 голосов
/ 06 ноября 2018

Я немного приготовил вашу программу и получил следующее:

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

int main(int argc, char *argv[])   // gets arguments when program ran, no arguments means argv=1
{
    int ret;
    pid_t pid; //process ID = pid
    pid=fork();
    char cwd[1024]; //compare directory to max character size
    char newPath[200]=".";
    if( argc > 1 )
    {
        strcpy(newPath,argv[1]);
    }
    ret=chdir(newPath);
    if( ret < 0 )
    {
        printf("Problem switching to :%s\n", newPath);
        perror("chdir");
        exit(ret);
    }
    if(pid==0){ //child has been forked! //child process created
        int ret;
        printf("Child PID=%d\n", getpid());
        getcwd(cwd, sizeof(cwd));
        printf(" My current working directory is: %s\n", cwd);

        ret= execl("/bin/ls", "ls", "-a", "-l", "-h",  NULL);
        printf("%d\n", ret); //why isn't this printed out?
    }
    else {
        int status;
        //parent process
        //wait for child to complete
        printf("Parent PID=%d\n", getpid());
        if (waitpid(pid, &status, 0) == -1) {
            printf("ERROR");
        } else
        {
            printf("Child done. stat=%d\n", status);
            getcwd(cwd, sizeof(cwd));
            printf("Parent cwd:%s\n", cwd);

            printf("0");
            exit(0);
        }
    }
}

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

Посмотрим:

  1. Я поместил chdir в вашей основной программе, чтобы показать, что ребенок следует за родителем.
  2. Дочерний процесс не собирается изменять рабочий каталог родителя. Unix и Linux не работают таким образом.
  3. Когда вы запускаете execl, это все. Нет возврата, если он не может выполнить. Суть exec * в том, что вы уничтожаете свою текущую программу новым исполняемым файлом Нечего возвращаться.
  4. Если вы хотите увидеть код возврата ребенка, посмотрите на статус, возвращаемый ожиданием. В этом случае ls работал нормально, поэтому код возврата равен нулю. Если вы добавите последний аргумент «baddir» (которого там нет), вы увидите ls ненулевой код возврата, в данном случае 512.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...