Выход из fork () в c - PullRequest
       70

Выход из fork () в c

0 голосов
/ 24 февраля 2019

Я недавно натолкнулся на этот кусок кода, и не до конца его понимаю.

  1. Какие обстоятельства могут вызвать pid == 0?
  2. Почему ожидание (NULL) вызывает переход программы в if (pid == 0)

По сути, я не совсем понимаю вывод ниже.Любая помощь будет оценена.Спасибо.

Код:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // standard POSIX header file
#include <sys/wait.h> // POSIX header file for 'wait' function
int main(void)
{
    int i = -1;
    int pid;
    pid = getpid();
    fprintf(stdout, "parent pid = %d\n", pid);
    pid = fork();

    if (pid == 0)
    {
        for (i = 0; i < 10; ++i)
        {
            fprintf(stdout, "child process: %d\n", i);
            sleep(1);
        }
        exit(0);
    }
    else
    {
        fprintf(stdout, "child pid = %d\n", pid);
        fprintf(stdout, "waiting for child\n");
        wait(NULL);
        fprintf(stdout, "child terminated\n");
    }
    fprintf(stdout, "parent terminating\n");
    return 0;
}

Вывод:

parent pid = 2896
child pid = 5840
waiting for child
child process: 0
child process: 1
child process: 2
child process: 3
child process: 4
child process: 5
child process: 6
child process: 7
child process: 8
child process: 9
child terminated
parent terminating

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019
  1. Системный вызов fork(2) создает второй дочерний процесс и, как следствие, вызов вызывается один раз в родительском, но возвращается как в родительском, так и в дочернем.

    В связи с этим код, следующий за вызовом, нуждается в некотором указании, чтобы знать, выполняем ли мы код в родительском или дочернем элементе, поскольку это позволяет родителю и дочернему элементу отклоняться от общего кода с этого момента.

    Определение fork(2), и оно указано на странице руководства:

    • , чтобы вернуть -1 и установить errno в значение, указывающее, почему вызов fork(2) не удался.
    • для возврата 0 для дочернего подпроцесса.
    • для возврата pid_t идентификатора дочернего процесса в родительский процесс (положительное число), чтобы он мог знать pid нового подпроцесса, который только что был запущен.
  2. wait(NULL); находится не в if (pid == 0), а в части else, поэтому он действительно находится в if (pid != 0) или в родительском процессе.,Родительский процесс должен знать, закончил ли ребенок и как, и должен синхронизироваться с ним по нескольким причинам:

    • ребенок может exit(2) перед родителем, но в зависимости от ребенкаобъем работы, которую он может выполнить после того, как родитель закончит.В случае, если родитель заканчивается перед дочерним, вы снова получите приглашение оболочки, и ваш экран будет размыт выводом дочернего сразу после того, как приглашение было выдано.Обычно это не то, что вам нужно, поэтому вызов wait(2) в родительском элементе является просто вежливым, поэтому оболочка запрашивает вас только после того, как все закончится.

      Хороший тест - прокомментировать вызов wait(2) вваш пример и посмотрите, что произойдет.

    • системный вызов wait(2) - это средство узнать, как ваш ребенок завершил выполнение (в основном, если вы exec(2) выполняли какую-то другую программу в дочернем процессе).) Вы можете узнать, умер ли ваш ребенок, потому что он exit(2) ed (и получил свой код выхода), потому что он был прерван (и каким был сигнал, который он получил) или был ли он остановлен пользователем / системой по какой-то причине.

Чтение системных вызовов fork(2), exec(2), exit(2) и wait(2) (все как группа связанных вызовов) прояснит всевзаимосвязи процессов и то, как все эти системные вызовы взаимодействуют для управления системой процессов unix.

0 голосов
/ 24 февраля 2019

Как указано в комментариях Susmit Agrawal и Джонатана Леффлера , чтобы кратко ответить на ваш первый вопрос:

0 - это возвращаемое значение внутри дочерний процесс после успешного возврата вызова fork().Выполнение дочернего процесса начинается в блоке if (pid == 0).Он повторяет цикл for, prints и sleeps в каждой итерации, затем в конце вызывается exit(0) и дочерний процесс завершается.

Выполнение родительского процесс после продолжения вызова fork() в блоке else. PID , возвращенный в родительском процессе , является PID ребенка.

Чтобы кратко ответить на ваш второй вопрос:

wait(NULL) используется для ожидания изменения состояния дочернего процесса.В этом конкретном случае изменение состояния является прекращением ребенка.Параметр NULL просто означает, что информация о состоянии не будет сохранена.

Для получения более подробной информации, пожалуйста, прочитайте связанные страницы руководства.

...