Сколько процессов создано в этой программе на С?

Это пример, который мне дали, и меня спросили, сколько процессов создано.

С

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

int main(void){
    int pid = (int)fork();
    pid = fork();
    pid = fork();
    printf("%d\n", pid);
    if (pid == 0){
        fork();
    }
    fork();

    return 0
}

Первоначально я вижу 5 вилок, поэтому 2 ^ 5 - 1 = 31 процесс. Однако быстро стало очевидно, что это не так, поскольку if (pid == 0){ fork(); } сбивает меня с толку.

Я изменил код, чтобы получить какой-то счет:

С

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

int count = 1;

int main(void){
    int pid = (int)fork(); 
    pid = fork(); 
    pid = fork(); 
    if (pid == 0){ 
       printf("2 ");
       fork(); 
    }
    fork(); 
    printf("1 ");
    return 0;
}

Результат: 1 1 1 1 2 1 1 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 1 2 1 2 1 2 1

Это 24 единицы и 8 двоек. Используя эту информацию, я бы предположил, что было создано 24-1 = 23 процесса, 8 из которых были созданы циклом if, но я просто не могу объяснить это, и если я должен минус 1 в первую очередь. Я был бы очень признателен за некоторый вклад в это спасибо.

С помощью ручки и бумаги нарисуйте дерево сгенерированных процессов.

Some programmer dude 21.02.2023 15:59

Если это становится сложным для понимания с первого взгляда, тогда в вашей голове должны загореться всевозможные предупреждающие огни, кричащие «ПЛОХОЙ ДИЗАЙН». Как это часто бывает с fork(). В случае, если вы должны настаивать на использовании fork(), тогда из любви к Unix slop инкапсулируйте каждое порождение в собственный модуль. То есть, как только вы вызвали эту проклятую вещь, проверьте, являетесь ли вы родителем или дочерним, затем вызовите функцию parent() или child() и т. д. и возьмите ее оттуда. Все остальное - сумасшествие и запутанность.

Lundin 21.02.2023 16:06

Добавьте гораздо больше операторов печати — и включайте PID и PPID в каждую операцию печати, каждый раз вызывая функции getpid() и getppid(). Непоследовательность кастинга fork() однажды немного озадачивает. Также стоит обратить внимание на информацию об аномалии printf() после fork(). Не доверяйте операциям printf с буферизованным выводом.

Jonathan Leffler 21.02.2023 16:07

Re «Это 24 единицы и 8 двоек»: только для больших значений 8, особенно 16.

Eric Postpischil 21.02.2023 16:08

@EricPostpischil: Как будто ему удалось мысленно раскрутить аномалию printf.

Joshua 21.02.2023 16:48
Руководство для начинающих по веб-разработке на React.js
Руководство для начинающих по веб-разработке на React.js
Веб-разработка - это захватывающая и постоянно меняющаяся область, которая постоянно развивается благодаря новым технологиям и тенденциям. Одним из...
Разница между Angular и React
Разница между Angular и React
React и AngularJS - это два самых популярных фреймворка для веб-разработки. Оба фреймворка имеют свои уникальные особенности и преимущества, которые...
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
0
5
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Мы видим, что программа всегда выполняется с одним оператором return.

Каждый процесс, который достигает пятого fork(), становится двумя процессами.

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

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

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

Каждый процесс, который достигает первого fork(), становится двумя процессами. Последующие вызовы fork() умножают это на 12, что дает 24.

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

Я действительно борюсь с вашим 3-м абзацем, так далеко от вершины у меня: P0 / | \ P1 P4 P2 / \ \ P3 P6 P5 / P7, и я действительно изо всех сил пытаюсь представить себе следующий шаг. Ну, это не очень хорошо, добавляя мой ответ

Nomad 21.02.2023 16:50
Ответ принят как подходящий

После первого форка у вас есть один родитель и один ребенок (всего 2).

После второй развилки у вас двое родителей и двое детей (всего 4).

После третьей развилки у вас четверо родителей и четверо детей (всего 8).

Затем каждый из 4 детей разветвляется, что дает вам в общей сложности 12.

Затем все процессы разветвляются, давая 24.

Другие вопросы по теме