Копируют ли дочерние процессы целые массивы? - PullRequest
2 голосов
/ 13 ноября 2011

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

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

Мне известно, что процесс выполняет операцию копирования при записи при записи в ранее определенную переменную.

Что мне интересно, так это то, что если я создам массив флагов, будет ли скопирован указатель на этот массив или будет скопирован весь массив (что сделает мою идею бесполезной).

Мне также хотелось бы получить советы по межпроцессному взаимодействию и синхронизации процессов.

РЕДАКТИРОВАТЬ: Процессы записывают друг другу канал процесса. Каждый процесс отправит следующую информацию:

typedef struct MessageCDT{
    pid_t destination;
    pid_t source;
    int num;
} Message;

Итак, просто источник сообщения и какое-то случайное число. Затем каждый процесс распечатывает сообщение для stdout: что-то вроде «процесса 20 получил 5724244 от процесса 3».

Ответы [ 2 ]

5 голосов
/ 13 ноября 2011

Процессы Unix имеют независимые адресные пространства.Это означает, что память в одном полностью отделена от памяти в другом.Когда вы вызываете fork (), вы получаете новую копию процесса.Сразу после возврата из fork () единственное, что отличается между двумя процессами, это возвращаемое значение fork ().Все данные в двух процессах одинаковы, но они являются копиями.Обновление памяти в одном не может быть известно другому, если вы не предпримете шаги для совместного использования памяти.

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

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

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

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

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

-Kevin

2 голосов
/ 13 ноября 2011

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

Есть способы, чтобы этого не случилось. Вы можете использовать mmap с опцией MAP_SHARED для памяти, используемой для ваших флагов. Тогда каждый подпроцесс будет использовать одну и ту же область памяти. Также есть общая память Posix (которую я, кстати, считаю ужасным взломом). Чтобы узнать об общей памяти Posix, обратитесь к справочной странице shm_overview(7).

Но использование памяти таким способом не очень хорошая идея. В многоядерных системах это не всегда тот случай, когда один процесс (или поток) записывает в область разделяемой памяти, что все остальные процессы сразу увидят записанное значение. Часто значение будет зависать на некоторое время в кэше L2 и не будет немедленно очищено.

Если вы хотите общаться с использованием общей памяти, вам придется использовать мьютексы или атомарные операции C ++ 11, чтобы гарантировать, что записи правильно видятся другими процессами.

...