Создайте N дочерних процессов из одного и того же процесса, затем напечатайте PID всех дочерних процессов с соответствующим родительским процессом - PullRequest
0 голосов
/ 04 мая 2019

Я до сих пор не понимаю, почему дочерний процесс с pid = 11310 создает дочерний процесс с pid = 11312

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


int main(){
    pid_t pid[2];
    for (int i = 0; i<2; i++){
        pid[i] = fork();
        if ( pid[i] == 0){  
            printf("[child] pid %d from [parent] pid %d\n",getpid(),getppid());
        }
    }
}

Мое ожидаемое:

[child] pid 11310 from [parent] pid 11309
[child] pid 11311 from [parent] pid 11309

Но фактические результаты:

[child] pid 11310 from [parent] pid 11309
[child] pid 11311 from [parent] pid 11309
[child] pid 11312 from [parent] pid 11310

1 Ответ

1 голос
/ 04 мая 2019

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

В первой итерации цикла for:

pid[i] = fork(); 
// this will create child process and both parent and child process proceed with next statement

if ( pid[i] == 0){ // only child process will enter to this if block
        printf("[child] pid %d from [parent] pid %d\n",getpid(),getppid());
}

Вывод на печать:

[child] pid 11310 from [parent] pid 11309

После выполнения тела цикла for значение переменной управления цикла i будет увеличиваться в адресном пространстве родительского и дочернего процессов из-за i++.

Итак, во второй итерации значение i равно 1 как в родительском, так и в дочернем адресном пространстве.

Теперь и родительский (PID: 11309), и дочерний (PID: 11310) будут выполнять тело цикла for, и оба будут создавать дочерний процесс. Вот почему дочерний процесс (PID: 11310) создает другого потомка (PID: 11312).

             11309-----    --|
               |      |      |---------> First iteration
             11310    |    --|   --|
               |      |            |---> Second iteration
             11312  11311        --|

На третьей итерации значение i будет 2 во всех процессах 4, а условие цикла i<2 приведет к false, и весь процесс завершится.

В вашем коде серьезная проблема - что произойдет, если родительский процесс завершится и завершится до дочернего процесса?
В этом случае дочерний процесс станет потерянным процессом , и вы можете получить родительский PID как 1 вместо исходного идентификатора родительского процесса, потому что потерянный процесс может быть переименован в init процесс, который обычно назначается PID 1.

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

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

int main(void) {
    pid_t pid;

    // You can take number of child process to be create as input from user

    for (int i = 0; i < 2; i++) {
        pid = fork();
        if (pid == 0) {
            printf("[child] pid %d from [parent] pid %d\n", getpid(), getppid());
            break;
        }
    }

    if (pid != 0) {
        int cpid;
        int status;
        while ((cpid = wait(&status)) > 0)
            printf("Parent (%d): child (%d) exited with status 0x%.4x\n", (int)getpid(), cpid, status);
    }

    return 0;
}

1) Существует концепция, называемая Copy-on-Write , которая представляет собой оптимизацию, при которой таблицы страниц настраиваются таким образом, чтобы родительский и дочерний процессы начинали совместно использовать одну и ту же память и только страницы, на которые записан какой-либо процесс, копируются при необходимости. Это означает, что и родительский, и дочерний процессы совместно используют копии одних и тех же данных, и как только один из них выполняет запись, копия создается, и любое изменение в памяти одного процесса не видно в другом.

...