Это пример, который мне дали, и меня спросили, сколько процессов создано.
С
#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 в первую очередь. Я был бы очень признателен за некоторый вклад в это спасибо.
Если это становится сложным для понимания с первого взгляда, тогда в вашей голове должны загореться всевозможные предупреждающие огни, кричащие «ПЛОХОЙ ДИЗАЙН». Как это часто бывает с fork(). В случае, если вы должны настаивать на использовании fork(), тогда из любви к Unix slop инкапсулируйте каждое порождение в собственный модуль. То есть, как только вы вызвали эту проклятую вещь, проверьте, являетесь ли вы родителем или дочерним, затем вызовите функцию parent() или child() и т. д. и возьмите ее оттуда. Все остальное - сумасшествие и запутанность.
Добавьте гораздо больше операторов печати — и включайте PID и PPID в каждую операцию печати, каждый раз вызывая функции getpid() и getppid(). Непоследовательность кастинга fork() однажды немного озадачивает. Также стоит обратить внимание на информацию об аномалии printf() после fork(). Не доверяйте операциям printf с буферизованным выводом.
Re «Это 24 единицы и 8 двоек»: только для больших значений 8, особенно 16.
@EricPostpischil: Как будто ему удалось мысленно раскрутить аномалию printf.
Мы видим, что программа всегда выполняется с одним оператором 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, и я действительно изо всех сил пытаюсь представить себе следующий шаг. Ну, это не очень хорошо, добавляя мой ответ
После первого форка у вас есть один родитель и один ребенок (всего 2).
После второй развилки у вас двое родителей и двое детей (всего 4).
После третьей развилки у вас четверо родителей и четверо детей (всего 8).
Затем каждый из 4 детей разветвляется, что дает вам в общей сложности 12.
Затем все процессы разветвляются, давая 24.
С помощью ручки и бумаги нарисуйте дерево сгенерированных процессов.