Проблемы с пониманием fork () и обработкой деревьев - PullRequest
0 голосов
/ 09 октября 2018

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

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

int main() {
    int status;
    pid_t i;

    i = fork();
    wait(&status);
    printf("a; i = %d\n", i);

    i = fork();
    wait(&status);
    printf("b; i = %d\n", i);

    i = fork();
    wait(&status);
    printf("c; i = %d\n", i);

    i = fork();
    wait(&status);
    printf("d; i = %d\n", i);

    return 0;
}

Кроме того, при выполнении этого кода выходные данные в 2 раза превышают те, которые я изначально предсказывал.Например, d печатается 16 раз, но я подумал, что он будет напечатан только 8 раз.Любое более глубокое объяснение было бы полезно.

1 Ответ

0 голосов
/ 09 октября 2018

Чтобы помочь себе понять, включайте PID и PPID в каждое заявление printf().Кроме того, захватывайте и сообщайте значение (PID мертвого ребенка), возвращаемое wait() каждый раз, когда оно вызывается;Вы можете решить, следует ли сообщать status или нет, но инициализировать его равным нулю в случае (если когда) вызовы wait() не будут выполнены, потому что нет дочернего элемента.Потом дети продолжают, прежде чем родитель возвращается из вызовов wait().

Или, лучше, напишите функцию регистрации, которая может обработать детали для вас.Например, рассмотрим следующий код:

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

static void print_info(const char *tag, int corpse, int status, int child)
{
    int pid = getpid();
    int ppid = getppid();
    printf("PID %5d, PPID %5d: %s (corpse: %5d, status 0x%.4X), child %5d\n",
            pid, ppid, tag, corpse, status, child);
}

int main(void)
{
    int pid = getpid();
    int ppid = getppid();
    printf("Initial PID %5d, PPID %5d:\n", pid, ppid);

    int status = 0;
    int child = fork();
    int corpse = wait(&status);
    print_info("a", corpse, status, child);

    child = fork();
    corpse = wait(&status);
    print_info("b", corpse, status, child);

    child = fork();
    corpse = wait(&status);
    print_info("c", corpse, status, child);

    child = fork();
    corpse = wait(&status);
    print_info("d", corpse, status, child);

    return 0;
}

Пример прогона дает мне:

Initial PID  7357, PPID 20754:
PID  7358, PPID  7357: a (corpse:    -1, status 0x0000), child     0
PID  7359, PPID  7358: b (corpse:    -1, status 0x0000), child     0
PID  7360, PPID  7359: c (corpse:    -1, status 0x0000), child     0
PID  7361, PPID  7360: d (corpse:    -1, status 0x0000), child     0
PID  7360, PPID  7359: d (corpse:  7361, status 0x0000), child  7361
PID  7359, PPID  7358: c (corpse:  7360, status 0x0000), child  7360
PID  7362, PPID  7359: d (corpse:    -1, status 0x0000), child     0
PID  7359, PPID  7358: d (corpse:  7362, status 0x0000), child  7362
PID  7358, PPID  7357: b (corpse:  7359, status 0x0000), child  7359
PID  7363, PPID  7358: c (corpse:    -1, status 0x0000), child     0
PID  7364, PPID  7363: d (corpse:    -1, status 0x0000), child     0
PID  7363, PPID  7358: d (corpse:  7364, status 0x0000), child  7364
PID  7358, PPID  7357: c (corpse:  7363, status 0x0000), child  7363
PID  7365, PPID  7358: d (corpse:    -1, status 0x0000), child     0
PID  7358, PPID  7357: d (corpse:  7365, status 0x0000), child  7365
PID  7357, PPID 20754: a (corpse:  7358, status 0x0000), child  7358
PID  7366, PPID  7357: b (corpse:    -1, status 0x0000), child     0
PID  7367, PPID  7366: c (corpse:    -1, status 0x0000), child     0
PID  7368, PPID  7367: d (corpse:    -1, status 0x0000), child     0
PID  7367, PPID  7366: d (corpse:  7368, status 0x0000), child  7368
PID  7366, PPID  7357: c (corpse:  7367, status 0x0000), child  7367
PID  7369, PPID  7366: d (corpse:    -1, status 0x0000), child     0
PID  7366, PPID  7357: d (corpse:  7369, status 0x0000), child  7369
PID  7357, PPID 20754: b (corpse:  7366, status 0x0000), child  7366
PID  7370, PPID  7357: c (corpse:    -1, status 0x0000), child     0
PID  7371, PPID  7370: d (corpse:    -1, status 0x0000), child     0
PID  7370, PPID  7357: d (corpse:  7371, status 0x0000), child  7371
PID  7357, PPID 20754: c (corpse:  7370, status 0x0000), child  7370
PID  7372, PPID  7357: d (corpse:    -1, status 0x0000), child     0
PID  7357, PPID 20754: d (corpse:  7372, status 0x0000), child  7372

Вы можете просматривать данные, видя, что их 2 4 процессы для вызовов 4 fork() (после каждого вызова есть 2 процесса, в которых до этого был 1 процесс, поэтому после одного вызова есть 2 процесса; после 2 вызовов, 4 процесса и т. д.) и что дочерний процессзавершает работу, прежде чем родитель продолжит работу (поэтому в этом примере PID 7357 является последним для печати тега a, тега b, тега c и тега d).

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

...