Как получить статус выхода дочернего процесса? - PullRequest
0 голосов
/ 01 ноября 2019

Два примера выходных данных (предоставленных моим профессором): (они вводятся в терминале Linux):

 ibrahim@ibrahim-latech:~$ ./prog2 .
 Current working directory: /home/ibrahim
 Executing ls . --all -l --human-readable
 total 24M
 drwxr-xr-x 74 ibrahim ibrahim 20K Oct 26 16:08 .
 drwxr-xr-x 6 root root 4.0K Apr 10 2014 ..
 -rw-r--r-- 1 ibrahim ibrahim 4.1K Sep 13 12:09 .bashrc
 drwxr-xr-x 7 ibrahim ibrahim 4.0K Oct 11 14:51 Desktop/
 ...snip...
 Exit status: 0

, поэтому состояние выхода равно 0, если код работает, но этот пример:

 ibrahim@ibrahim-latech:~$ ./prog2 /root
 Current working directory: /home/ibrahim
 Executing ls /root --all -l --human-readable
 Can't chdir to /root
 Exit status: 1 

Состояние выхода равно 1, поскольку оно ложно.

Вот мой код:

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

int main(int argc, char *argv[]){
    pid_t pid;
    pid = fork();
    char cwd[255];
    if(pid == 0){
        printf("Current working directory: %s\n",getcwd(cwd, sizeof(cwd)));
        printf("Executing ls %s --all -l --human-readable\n",argv[1]);
        if(chdir(argv[1])!=0){
            printf("this is not a valid directory");
        }
        else{
            execl("/bin/ls","ls","--all","-l","--human-readable", NULL);
        }
    }
    else{
        wait(NULL):
        printf("Exit status:");// not sure how to put the 1 or 0 in this
    }
}

Состояние выхода должно быть выведено из родительского процесса. Я не могу понять, как заставить работать статус выхода.

1 Ответ

2 голосов
/ 01 ноября 2019

Передача ключевой информации из комментариев в ответ.

Функция wait() сообщает вам PID и статус выхода -Вы просто должны захватить их, а не игнорировать их. Вам нужно будет использовать WIFEXITED и WEXITSTATUS (и если WIFEXITED сообщает false, есть другие макросы для сигналов и дампов ядра и т. Д.).

Изменение кода:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

#ifndef LS_PATH
#define LS_PATH "/bin/ls"
#endif

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s directory\n", argv[0]);
        return 1;
    }
    pid_t pid = fork();
    if (pid == 0)
    {
        char cwd[255];
        printf("Current working directory: %s\n", getcwd(cwd, sizeof(cwd)));
        printf("Executing 'ls -a -l' in %s\n", argv[1]);
        if (chdir(argv[1]) != 0)
        {
            fprintf(stderr, "%s: %s is not a valid directory\n", argv[0], argv[1]);
            return 1;
        }
        //execl(LS_PATH, "ls", "--all", "-l", "--human-readable", (char*) NULL);
        execl(LS_PATH, "ls", "-a", "-l", (char*) NULL);
        fprintf(stderr, "Failed to execute %s\n", LS_PATH);
        return 1;
    }
    else
    {
        int status;
        int corpse = wait(&status);
        if (corpse < 0)
            printf("Failed to wait for process %d (errno = %d)\n", (int)pid, errno);
        else if (corpse != pid)
            printf("Got corpse of process %d (status 0x%.4X) when expecting PID %d\n",
                   corpse, status, (int)pid);
        else if (WIFEXITED(status))
            printf("Process %d exited with normal status 0x%.4X (status %d = 0x%.2X)\n",
                   corpse, status, WEXITSTATUS(status), WEXITSTATUS(status));
        else if (WIFSIGNALED(status))
            printf("Process %d exited because of a signal 0x%.4X (signal %d = 0x%.2X)\n",
                   corpse, status, WTERMSIG(status), WTERMSIG(status));
        else
            printf("Process %d exited with status 0x%.4X which is %s\n",
                   corpse, status, "neither a normal exit nor the result of a signal");
    }
    return 0;
}

Я работаю на Mac, который не использует GNU ls, поэтому я сделал код настраиваемым во время компиляции для местоположения ls, и он использует только переносимые параметры (-a и -l а не опции двойной тире). Я изменил сообщение и обнаружил еще несколько ошибок. Как и ваш код, предполагается, что fork() не дает сбоя - он также должен проверять наличие ошибки там.

Пример вывода (сокращенно) - из программы es61, скомпилированной из es61.c:

$ es61 /orthography
Current working directory: /Users/jonathanleffler/soq
Executing 'ls -a -l' in /orthography
es61: /orthography is not a valid directory
Process 64463 exited with normal status 0x0100 (status 1 = 0x01)
$ es61 $PWD
Current working directory: /Users/jonathanleffler/soq
Executing 'ls -a -l' in /Users/jonathanleffler/soq
total 1016
drwxr-xr-x  100 jonathanleffler  staff   3200 Oct 31 15:53 .
drwxr-xr-x+  69 jonathanleffler  staff   2208 Oct 31 15:53 ..
…
-rwxr-xr-x    1 jonathanleffler  staff   9028 Oct 31 15:53 es61
-rw-r--r--    1 jonathanleffler  staff   1806 Oct 31 15:53 es61.c
drwxr-xr-x    3 jonathanleffler  staff     96 Oct 31 15:43 es61.dSYM
drwxr-xr-x    9 jonathanleffler  staff    288 Nov  5  2018 etc
…
-rw-r--r--    1 jonathanleffler  staff    390 Nov 16  2017 makefile
…
Process 64557 exited with normal status 0x0000 (status 0 = 0x00)
$
...