Создание нескольких дочерних с помощью fork () в Linux - PullRequest
2 голосов
/ 14 марта 2012

Я хочу создать нескольких детей, используя fork(), но у меня возникли проблемы. LIKE:

///////////////////////// these are some class objects creation and calling
//  There are some functions calling from another class. about 5 functions I invoked.
// and some variables like.

    pid_t PID;
    int status = 0;
    char *x = new char[10];

///////////////////////// This for loop give me multiple children
// now one parent have multiple children in this case 10


    for( int i=0; i<10; i++ )
    {
        mNo++;
        rNo++;
        PID = fork();

        if( PID == FORK_ERROR )         // fork ERROR!
        {
            fprintf(stderr, "ERROR! In fork() [FORCE EXITING]... %d\n", errno);
            exit(EXIT_FAILURE);
        }
        else if( PID == CHILD )         // Do Child Stuff Here...
        {
            exit(status);
        }
        else            // Do parent Stuff Here...
        {

        }
    }
    PID = wait(&status);

////////////////////////////////////////////

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

Я хочу спросить, что когда я создаю ребенка в памяти, он создает дубликат памяти. Также объекты, которые я объявил; их повторно вызывают, вызывая fork(), значит ли это, что для каждого ребенка в памяти есть объекты, которые повторно вызывают в классе?

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

Более того, я повторяю свой вопрос, что если я fork(), что происходит с объектами и переменными. Перед вызовом fork они просто перераспределяются или их снова вызывают для каждого ребенка? Но то, что я вижу, это то, что их повторно вызывают за каждого ребенка, чего я не хочу. Так что мне делать?

Ответы [ 4 ]

2 голосов
/ 14 марта 2012

Поведение fork() не изменится в соответствии с вашими желаниями.

Когда процесс разветвляется, появляются две практически идентичные копии одной и той же программы. Различия перечислены на странице руководства POSIX (ссылка выше). Память такая же. Например, объекты в C ++ не будут реконструированы. Например, в каждом из этих процессов все синглеты по-прежнему будут синглетонами.

Не могли бы вы привести пример?

Вот полная основная программа из того, что я написал в 1991 году. Я только обновил ее, чтобы использовать прототип для main(), и включил typedef для Pipe и определение id:

static char id[] = "\n\n\nSQLMONITOR version 3.5 \n";
typedef int Pipe[2];

int main(int argc, char **argv)
{
    int     pid;
    Pipe    to_sqlexec;
    Pipe    from_sqlexec;

    setarg0(argv[0]);
    write(STDERR, id, sizeof(id)-1);
    if (pipe(to_sqlexec) < 0 || pipe(from_sqlexec) < 0)
        error("unable to create pipes");
    else if ((pid = fork()) < 0)
        error("unable to fork");
    else if (pid == 0)
        be_childish(argv, to_sqlexec, from_sqlexec);
    else
        be_parental(to_sqlexec, from_sqlexec);
    return(0);
}

Функция be_childish() продолжала выполнять некоторые операции (дублирование и закрытие соответствующих частей каналов перед выполнением другой программы. Процесс be_parental() продолжал читать сообщения со своего стандартного ввода, записывать их в файл, и записывает сообщения на стандартный ввод его потомка по стороне записи канала to_sqlexec, затем он читает ответ от потомка со стороны чтения канала from_sqlexec и записывает это сообщение тоже , а затем запишите его в стандартный вывод. Таким образом, он будет сидеть в середине двух процессов, записывая все, что переходило от одного к другому. Протокол связи между процессами был синхронным, что значительно упрощало жизнь. С другой стороны , когда данные из одного процесса были завершены, было довольно сложно разобраться.Код предшествовал широко распространенной доступности select() и poll(), в настоящее время не нужно было бы выполнять такой большой анализ сообщений.

Ключевым моментом, однако, является то, что эти два канала одинаковы в обоих процессах после fork(); действительно, единственная отличающаяся переменная - это pid, которая получает возвращаемое значение от fork(). Все остальное точно так, как было до fork().

2 голосов
/ 14 марта 2012

Когда вы выполняете ветвление, ваш ребенок является копией родительского процесса, включая кучу.Следовательно, у вас есть отдельная копия ваших объектов или память, выделенная с помощью new.Я не уверен, что вы подразумеваете под повторным вызовом, но у вас будет 2 отдельных объекта в 2 отдельных кучах в 2 отдельных процессах, если вы выделили объект с помощью new () в родительском объекте.Один будет исходным в родительском процессе, а другой - копией скопированной кучи в дочернем процессе.

Это поможет лучше понять: Разветвление Linux внутри класса в куче

1 голос
/ 14 марта 2012

Если вы раскошелитесь, я думаю, что все объекты и переменные будут точно такими же, как родительский процесс.Я не понимаю под словами «но что я вижу, что их повторно вызывают за каждого ребенка», что здесь повторяется?

1 голос
/ 14 марта 2012

Похоже, вы не знаете, что делает fork ().Это делает странным то, что вы уверены, что это правильная функция.

Читайте об этом:

http://linux.die.net/man/2/fork

http://en.wikipedia.org/wiki/Fork_(operating_system)

ПриНа первый взгляд кажется, что дочерние процессы получают копию памяти родителя.

...