Функция Fork() в C
Ниже приведен пример функции Fork в действии. Ниже также вывод. Мой главный вопрос, связанный с вилкой, называется изменением значений. Таким образом, pid1,2 и 3 начинаются с 0 и меняются по мере того, как вилки случаются. Это потому, что каждый раз, когда вилка происходит, значения копируются в дочерний элемент, а конкретное значение изменяется в родительском? В основном, как значения изменяются с помощью функций fork?
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t pid1, pid2, pid3;
pid1=0, pid2=0, pid3=0;
pid1= fork(); /* A */
if(pid1==0){
pid2=fork(); /* B */
pid3=fork(); /* C */
} else {
pid3=fork(); /* D */
if(pid3==0) {
pid2=fork(); /* E */
}
if((pid1 == 0)&&(pid2 == 0))
printf("Level 1\n");
if(pid1 !=0)
printf("Level 2\n");
if(pid2 !=0)
printf("Level 3\n");
if(pid3 !=0)
printf("Level 4\n");
return 0;
}
}
Тогда это выполнение.
----A----D--------- (pid1!=0, pid2==0(as initialized), pid3!=0, print "Level 2" and "Level 4")
| |
| +----E---- (pid1!=0, pid2!=0, pid3==0, print "Level 2" and "Level 3")
| |
| +---- (pid1!=0, pid2==0, pid3==0, print "Level 2")
|
+----B----C---- (pid1==0, pid2!=0, pid3!=0, print nothing)
| |
| +---- (pid1==0, pid2==0, pid3==0, print nothing)
|
+----C---- (pid1==0, pid2==0, pid3!=0, print nothing)
|
+---- (pid1==0, pid2==0, pid3==0, print nothing)
В идеале ниже показано, как я хотел бы, чтобы это объяснялось, поскольку этот способ имеет смысл для меня. В этом моя главная путаница. Когда дочерние вилки, например, pid1 = fork();
, который создает процесс со всеми значениями родительского элемента, но делает ли он это значение, например, разрешает говорить 1 родителям pid1? Значение у ребенка было бы pid 1 = 0, pid2 = 0 и pid3 = 0, а родительский тогда как pid1 = 2 и pid2 и 3 равны 0? ![введите описание изображения здесь]()
Ответы
Ответ 1
Системный вызов fork() используется для создания процессов. Он не принимает аргументов и возвращает идентификатор процесса. Цель fork() - создать новый процесс, который станет дочерним процессом вызывающего. После создания нового дочернего процесса оба процесса будут выполнять следующую команду после системного вызова fork(). Поэтому мы должны отличить родителя от ребенка. Это можно сделать, проверив возвращаемое значение fork()
Fork - системный вызов, и вы не должны думать об этом как о нормальной функции C. Когда fork() встречается , вы эффективно создаете два новых процесса со своим собственным адресным пространством. Переменные, инициализированные до вызова fork(), сохраняют одни и те же значения в обоих адресных пространствах. Однако значения, измененные в адресном пространстве любого из процессов, остаются незатронутыми в другом процессе, один из которых является родительским, а другой - дочерним.
Поэтому, если
pid=fork();
Если в последующих блоках кода вы проверяете значение pid. Оба процесса выполняются для всей длины вашего кода. Итак, как мы их различаем.
Снова Вилка - системный вызов, а вот разница. Внутри вновь созданного дочернего процесса pid будет хранить 0, а в родительском процессе - сохранить положительное значение. Отрицательное значение внутри pid указывает на ошибку fork.
Когда мы тестируем значение pid
чтобы определить, равна ли она нулю или большему, чем мы, мы эффективно обнаруживаем, находимся ли мы в дочернем процессе или родительском процессе.
Подробнее о вилке
Ответ 2
int a = fork();
Создает дублирующий процесс "clone?", который разделяет стеки выполнения. Разница между родительским и дочерним является возвращаемым значением функции.
Ребенок получает 0, а родитель получает новый pid.
Каждый раз, когда копируются адреса и значения переменных стека. Выполнение продолжается в той точке, в которой он уже попал в код.
В каждом fork
изменяется только одно значение - возвращаемое значение из fork
.
Ответ 3
Сначала ссылка на некоторую документацию fork()
http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html
pid предоставляется ядром. Каждый раз, когда ядро создает новый процесс, он увеличит внутренний счетчик pid и назначит новый процесс новому уникальному pid, а также убедитесь, что дубликатов нет. Как только pid достигнет некоторого большого количества, он обернется и начнется снова.
Итак, вы никогда не знаете, какой pid вы получите от fork(), только чтобы родитель сохранил его уникальный pid, и эта вилка будет следить за тем, чтобы дочерний процесс имел новый уникальный pid. Это указано в приведенной выше документации.
Если вы продолжите чтение документации, вы увидите, что fork() возвращает 0 для дочернего процесса, и новый уникальный pid дочернего элемента будет возвращен родительскому элементу. Если ребенок хочет знать его собственный новый pid, вам придется запросить его, используя getpid().
pid_t pid = fork()
if(pid == 0) {
printf("this is a child: my new unique pid is %d\n", getpid());
} else {
printf("this is the parent: my pid is %d and I have a child with pid %d \n", getpid(), pid);
}
и ниже приведены некоторые встроенные комментарии к вашему коду
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t pid1, pid2, pid3;
pid1=0, pid2=0, pid3=0;
pid1= fork(); /* A */
if(pid1 == 0){
/* This is child A */
pid2=fork(); /* B */
pid3=fork(); /* C */
} else {
/* This is parent A */
/* Child B and C will never reach this code */
pid3=fork(); /* D */
if(pid3==0) {
/* This is child D fork'ed from parent A */
pid2=fork(); /* E */
}
if((pid1 == 0)&&(pid2 == 0)) {
/* pid1 will never be 0 here so this is dead code */
printf("Level 1\n");
}
if(pid1 !=0) {
/* This is always true for both parent and child E */
printf("Level 2\n");
}
if(pid2 !=0) {
/* This is parent E (same as parent A) */
printf("Level 3\n");
}
if(pid3 !=0) {
/* This is parent D (same as parent A) */
printf("Level 4\n");
}
}
return 0;
}