Действительно ли это - безопасный способ совместно использовать постоянную память с дочерними процессами?

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

Действительно ли я прав в размышлении что если я malloc память, как обычно, затем отметьте его как только для чтения с mprotect(addr, size, PROT_READ) и затем fork, это позволит дочерним процессам безопасно использовать память, не заставляя это быть скопированным? (Если я удостоверяюсь, что ничто не пытается записать в выделенную память после mprotect звоните).

править: Спасибо за все ответы.

Последующий вопрос - я был планированием использования shmget, но я думал, что это использовало mm и таким образом был бы ограничен меньшими выделениями (см. раздел Restrictions этой страницы). например, /proc/sys/kernel/shmmax 32 МБ на сервере, я использую этого. Но я хочу 1 ГБ непрерывной памяти. Я неправильно об этом ограничении?

7
задан John Carter 10 February 2010 в 09:36
поделиться

6 ответов

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

  Day    |  Count
__________________
 Monday        5
 Tuesday       4
 Monday        6
 Tuesday       3
 ...          ...

Тогда вы можете усреднить эти числа. I.e (5 + 6 )/2 для понедельника.
Что-то подобное должно сработать:

SELECT day_of_week, AVG(order_count) average_order FROM 
(
  SELECT DAYNAME(order_date) day_of_week, 
         DAYOFWEEK(order_date) day_num, 
         TO_DAYS(order_date) date,
         count(*) order_count
  FROM data 
  GROUP BY date
) temp
GROUP BY day_of_week 
ORDER BY day_num

ОБНОВЛЕНИЕ: Я изначально ошибался. Сгруппируйте внутренний SELECT по фактической дате, чтобы получить правильные дневные итоговые значения. Например, вы должны получить, сколько заказов произошло в понедельник (2/1/10) и понедельник (2/8/10) по отдельности. Затем усредните эти итоговые значения по дням недели.

-121--4746311-

Источник данных предоставляет данные, а делегат - поведение.

В MVC источник данных находится на уровне модели, а делегат - на уровне управления.

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

-121--1187609-

man mprotect

Реализация потребует, чтобы addr был кратен размеру страницы, возвращаемому sysconf () .

Поведение этой функции не определено, если отображение не было установлено вызовом mmap () .

  1. mprotect работает только на страницах, а не в произвольных диапазонах байтов, поэтому в целом malloc неуместен. posix _ memalign может помочь, но...
  2. Несмотря на то, что система может работать в настоящее время, вы кричите не mprotect ничего, что вы не mmap самостоятельно. Вместо этого используйте mmap (0, pages * sysconf (_SC_PAGESIZE), PROT_READ'PROT_WRITE, MAP_SHARED'MAP_ANONYMOUS, -1, 0) .
7
ответ дан 6 December 2019 в 19:36
поделиться

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

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

Вместо того чтобы использовать нестандартное поведение, вы можете использовать стандартные меры для разделения памяти. Например, POSIX разделяет память с помощью shm_open и последующего mmap (как было указано в комментарии и объяснено в посте от ephemient). Дескриптор файла будет сохранен при форкинге.

3
ответ дан 6 December 2019 в 19:36
поделиться

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

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

Если вы хотите писать на него, вам нужно использовать mmap с MAP_SHARED.

2
ответ дан 6 December 2019 в 19:36
поделиться

Вы делаете предположение, что ядро будет делать копирование при записи оптимизацию и не копировать mprotect-ые страницы. Однако я бы на это не рассчитывал. malloc-ed память имеет всевозможные метаданные, плавающие вокруг нее - страницы охраны, и т.д. и т.п. и только Ульрих Дреппер знает, что происходит внутри libc :)

Возможно, было бы проще и безопаснее подготовить данные в дисковом файле и mmap их во все процессы, или просто пойти обычным POSIX shm_open путем.

1
ответ дан 6 December 2019 в 19:36
поделиться

Вы можете сделать это таким же образом.

Альтернативой является использование mmap () .

Другой альтернативой является использование разделяемой памяти POSIX ( shm_open () ); другой основной альтернативой является разделяемая память System V ( shmget () , shmat () ). Одним из преимуществ формальных систем с общей памятью является то, что ваш родительский процесс может создавать память, а затем к ней может подключаться несвязанный процесс - если это было выгодно.

0
ответ дан 6 December 2019 в 19:36
поделиться

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

0
ответ дан 6 December 2019 в 19:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: