Общие библиотеки, конструкторы объектов и поведение fork () - PullRequest
1 голос
/ 02 марта 2011

g ++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3. Отредактировано для ясности.

У меня есть общая библиотека, в которой я хочу что-то сделать при первой загрузке и когда на нее больше нет ссылок.

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

Каждый работал одинаково. Затем я создал тестовую программу, которая использует библиотеку и fork () из процесса. Оказывается, конструктор вызывается только один раз, а деструктор вызывается дважды - один раз для каждого процесса.

Это ожидаемое поведение для разделяемых библиотек и fork (), или я здесь что-то не так делаю? Кажется очень опасным, чтобы dtors вызывался для каждого процесса, а ctor вызывался только один раз.

Общая библиотека (g ++ -fPIC -c -o myshare.o myshare.cpp / g ++ -shared -o libmyshare.so myshare.o):

class SharedMemAccess
{
public:
    SharedMemAccess();
    ~SharedMemAccess();
};

static SharedMemAccess g_sharedMem;

SharedMemAccess::SharedMemAccess()
{    
    LOGDEBUG("Constructor\n");return;
}

SharedMemAccess::~SharedMemAccess()
{
    LOGDEBUG("Destructor\n");return;
}

Тестовый драйвер (g ++ -c -o main.o main.cpp / g ++ main.o -lmyshare -o test):

int main()
{    
    LOGDEBUG("In main\n");

    pid_t rc = fork();  
    if (rc == -1)      LOGDEBUG("fork failed\n");
    else if (rc == 0)  ChildProcess();
    else               ParentProcess();

    return 0;
}

void ChildProcess()
{
    LOGDEBUG("Child process spawned.\n");    
    usleep(10 * 1000 * 1000);    
    LOGDEBUG("Child process exiting.\n");
}

void ParentProcess()
{
    LOGDEBUG("Parent process spawned.\n");
    usleep(5 * 1000 * 1000);
    LOGDEBUG("Parent process exiting.\n");
}

Выход:

16:10:28 SharedMemAccess(  59): Constructor
16:10:28 main(  25): In main
16:10:28 ParentProcess(  62): Parent process spawned.
16:10:28 ChildProcess(  47): Child process spawned.
16:10:33 ParentProcess(  72): Parent process exiting.
16:10:33 ~SharedMemAccess( 133): Destructor
16:10:38 ChildProcess(  57): Child process exiting.
16:10:38 ~SharedMemAccess( 133): Destructor

Спасибо,

-Joe

Ответы [ 2 ]

5 голосов
/ 02 марта 2011

Это не "общая память". Вы только «делитесь» объектами в очень ослабленном смысле - fork () делает копию уже созданного родительского объекта как часть копирования всего родительского процесса.

В качестве подробностей реализации в большинстве операционных систем вы получаете семантику копирования при записи (поэтому один и тот же физический бит памяти будет использоваться до тех пор, пока один процесс не попытается каким-либо образом изменить страницу), но изменения из одного процесса не будет видимым в другом, и с точки зрения программиста экземпляр объекта родителя полностью отличается от экземпляра дочернего элемента. Семантика COW предназначена только для оптимизации производительности и эффективности.

Вы можете прочитать о реальных методах совместного использования памяти / объектов с помощью некоторого поиска в Google. Руководство по IPC от Beej содержит хорошее введение в одну из форм разделяемой памяти .

Однако семантика фактической разделяемой памяти не точно будет соответствовать семантике обычного конструирования / уничтожения объектов C ++.

0 голосов
/ 18 сентября 2012

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

Вы можете использовать "pidof", чтобы получить список PID для именованного процесса: pidof chrome

Используя другие инструменты, вы можете легко определить, сколько других процессов все еще активно. Это полезно для конвейерной передачи в sed для создания списка, разделенного запятыми, и последующего использования в качестве входных данных для отслеживания ваших процессов после перезапуска.

...