Разветвление Linux внутри класса в куче - PullRequest
4 голосов
/ 21 февраля 2011

Что происходит, когда у меня следующая ситуация:

класс A: удерживает динамически размещенные объекты B.Он создаст и уничтожит их.

класс B: имеет функцию execute, вызванную A. Execute выполнит fork (), и дочерний процесс будет использовать execvp для запуска другого процесса.НО, можно установить флаг, чтобы родитель не ожидал ребенка (позволяет ему работать в фоновом режиме).

Мой вопрос: что делает в этом случае fork?Я знаю, что у ребенка есть полная копия процесса родителя, но я немного растерялся.Значит ли это, что дочерний процесс имеет свой собственный объект A, который содержит B?И что произойдет, если B не ждет, но A удаляет B?

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

class B;
class A
{
    public:
    void addAction( const std::string &name )
    {
        _bq.push( new B( name ) );
    }

    void doActions( bool wait = true )
    {
        while ( !_bq.empty() )
        {
            B* b = _bq.front();
            b->execute( wait );
            _bq.pop();
            delete b;
        }
    }

    ~A() { //omitted, but just deletes everything in queue }

    private:
    std::queue<B*> _bq;
};

class B
{
    public:
    B( const std::string &name )
    {
        args.push_back( name.c_str() );
        args.push_back( NULL );
    }
    void execute( bool waitForChild )
    {
        pid_t pid = fork();
        if ( pid != 0 )
        {
            if (waitForChild)
            {
                int status;
                wait( &status );
                // check status...
             }
        }
        else
        {
            execvp( args[0], const_cast<char**>( &args[0] ) );
            // problem
            exit( 100 );
        }
    }
    private:
    std::vector<char*> args;
};

Ответы [ 3 ]

4 голосов
/ 21 февраля 2011

Дочерний процесс полностью отделен от родительского и имеет полную копию родительских переменных. Когда ребенок выполняет (вызывает execve() или одного из его родственников), деструкторы C ++ не выполняются. Однако это никак не влияет на родительский процесс.

Итак, нет никакого вмешательства между ребенком и процессом. Не имеет значения, ждет ли родитель ребенка или нет. Как только fork() возвращает (успешно) в родительский процесс, дочерний процесс выполняется независимо, и ничто из того, что родитель делает с распределенными переменными, не повлияет на дочерний процесс.

Если вы действительно стараетесь и у вас есть общая память и переменные, выделенные в разделяемую память посредством размещения new, и если ребенок выполняет очистку переменных в разделяемой памяти перед вызовом execvp(), или какой-либо другой аналогично надуманной, но не на самом деле Невозможный сценарий, то ребенок и родитель не полностью независимы. Однако, если бы вы делали что-то более сложное, вы, вероятно, тоже не задавали бы вопрос.

2 голосов
/ 21 февраля 2011

Когда вы разветвляете свой процесс, вы получаете полную копию процесса (хотя обычно он выполняется с использованием копирования при записи), и под «полной копией» я подразумеваю полную копию;включая различные страницы, которые были выделены для этого процесса, так что логически есть целая другая копия кучи и, для каждого потока, копия этого потока и связанного с ним стека, так что да, у вас есть две копии A и B.

Тем не менее, более насущный вопрос, что касается разветвления, что происходит с потоками?Или что произойдет, если вы добавите хук atfork для одного из ваших потоков?Это один из немногих способов, которыми fork + exec может быть довольно неработоспособным или трудным для использования в контексте UNIX.Обычно лучше решить эту проблему один раз с помощью библиотеки или использовать popen, а не пытаться решить ее несколько раз повсеместно.

0 голосов
/ 21 февраля 2011

Вилка скопирует кучу вместе с остальными данными процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...