Что происходит, когда fork () в состоянии? - PullRequest
0 голосов
/ 14 февраля 2020

Может кто-нибудь дать мне вывод (с объяснением) этого кода? Спасибо ...

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

int main() 
{ 
    if (fork() && (!fork())) { 
        if (fork() || fork()) {
            fork(); 
        } 
    } 
    printf("Friend\n");
    return 0; 
}

Ответы [ 2 ]

1 голос
/ 14 февраля 2020

Быстрый ответ: родитель сделает что-то, а ребенок сделает что-то еще. Но продолжайте читать ...

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

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

static pid_t my_fork() /* tracing is your friend! :) */
{
    pid_t chld = fork();
    if (chld > 0) {
        /* only the parent shows this */
        printf("[pid=%d, child=%d] forked!\n",
                getpid(), chld);
    }
    return chld;
}

int main() 
{ 
    /* print our pid, so we know the root of the hierarchy */
    printf("[pid=%d] Hello, world\n", getpid());

    /* do the embarrasing work */
    if (my_fork() && (!my_fork())) { 
        if (my_fork() || my_fork()) {
            my_fork(); 
        } 
    } 

    pid_t pid;
    int status;

    /* We do wait(2)'s while there are children to be waited for. 
     * it's a good thing to wait for children before ending. */
    while((pid = wait(&status)) >= 0) {
        printf("[pid=%d, child=%d]: child ended with status=%d\n",
                getpid(), pid, status);
    }

    /* we print the message when no more children are alive */
    printf("[pid=%d]: Hello friend!\n", getpid());

    return 0; 
}

, и это приводит к

$ pru
[pid=72699] Hello, world
[pid=72699, child=72700] forked!
[pid=72699, child=72701] forked!
[pid=72700]: Hello friend!
[pid=72701, child=72702] forked!
[pid=72703]: Hello friend!
[pid=72699, child=72700]: child ended with status=0
[pid=72702, child=72703] forked!
[pid=72702, child=72705] forked!
[pid=72702, child=72703]: child ended with status=0
[pid=72705]: Hello friend!
[pid=72704]: Hello friend!
[pid=72701, child=72704] forked!
[pid=72701, child=72704]: child ended with status=0
[pid=72702, child=72705]: child ended with status=0
[pid=72702]: Hello friend!
[pid=72701, child=72702]: child ended with status=0
[pid=72701]: Hello friend!
[pid=72699, child=72701]: child ended with status=0
[pid=72699]: Hello friend!

, и это иерархия:

[pid=72699] (says Hello, world, just starting)
  +-[pid=72700] (created in first fork() call of pid=72699)
  `-[pid=72701] (created in second fork() call of pid=72699)
     +-[pid=72702] (created in third fork() call of pid=72701)
     |  +-[pid=72703] (created in fourth fork() call of pid=72702)
     |  `-[pid=72705] (created in fifth fork() call of pid=72702)
     `-[pid=7204] (created in fourth fork() call of pid=72701)

(конечно, иерархия будет другой, если у вас закончатся процессы, и fork(2) терпит неудачу из-за нехватки системных ресурсов)

Наконец, вы, вероятно, будете беспокоиться о том, почему сообщение

[pid=72703]: Hello friend!

появляется перед сообщением

[pid=72702, child=72703] forked!

но это удивительный мир многозадачности. Сообщение печатается после возврата fork(2), поэтому оба сообщения печатаются разными процессами, поэтому их можно запланировать в любом порядке, поэтому ребенок запускает и печатает свое сообщение, прежде чем родитель сможет распечатать, кто его ребенок. Это совершенно нормально.

ПРИМЕЧАНИЕ

Вы должны знать, что fork() возвращает -1 в случае ошибки, которая в булевом тесте оценивается как true, так же, как родительский результат. Так что, если вы свободно используете коды возврата из fork(2) для логических выражений, родитель получит true или любую ошибку, которая произойдет, если fork() не получится (ну, они редки, но возможны в загруженной системе) , Просто сохраните код результата fork() и сначала проверьте на наличие ошибок, а затем вы можете использовать любое логическое выражение, которое вам нужно.

Исходный код выше можно загрузить здесь

1 голос
/ 14 февраля 2020

До go в коде лучше понять, что такое системный вызов fork ()

Системный вызов fork () создает новый процесс с помощью 'parent', а недавно созданный процесс называется 'дочерний' процесс

дочерний процесс возвращает 0, а родительский возвращает положительное целое число, когда fork является успешным

В этом ключ

Так что все два процесса работают одновременно с этим счетчиком программы далее ...

здесь fork () находится в условии if, и это немного сложнее при угадывании вывода

  1. first fork () создает новый C1 -> 0

  2. вторая ветвь () создает новый C2 ->! 0 -> 1

, поэтому первое условие определяется C2 (который родительское положительное целое число и c2 равно 0), но не проверено ни родителем, ни дочерним элементом C1, поэтому другие вилки не будут работать

, а затем C2 go в другом условии, если это условие, и пометили еще две вилки

            C2
          /    \
         C2     C3
       /   \   /  \
      C2   c4  c3  c5

Тогда все созданные процессы (включая родительские) p печатает вывод "Друг" 7 раз

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...