2010-09-06 4 views
0

Я работаю над Linux для процессора ARM для кабельного модема. Существует инструмент, который я написал, который отправляет/штурмует настроенные UDP-пакеты с использованием сырых сокетов. Я формирую пакет с нуля, так что у нас есть возможность играть с различными параметрами. Этот инструмент предназначен в основном для стресс-тестирования маршрутизаторов.Оптимизация памяти для дочерних процессов

У меня на самом деле создано несколько интерфейсов. Каждый интерфейс получит IP-адреса, используя DHCP. Это делается для того, чтобы модем работал как оборудование виртуального клиентского помещения (vcpe).

Когда система появляется, я запускаю те процессы, которые требуются. Каждый процесс, который я запускаю, будет непрерывно отправлять пакеты. Таким образом, процесс 0 будет отправлять пакеты с использованием интерфейса 0 и т. Д. Каждый из этих процессов, которые отправляют пакеты, разрешает настройку (изменение параметров UDP и других параметров во время выполнения). Именно поэтому я решил иметь отдельные процессы.

Я запускаю эти процессы, используя fork и excec из процессов инициализации модема.

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

Я попытался следующие:

Я всегда считал, что толкая больше кода для библиотек Shared поможет. Поэтому, когда я попытался переместить многие функции в общую библиотеку и сохранить минимальный код в процессах, это не имело никакого значения для моего удивления. Я также удалил все массивы и заставил их использовать кучу. Однако это не имело никакого значения. Это может быть потому, что процессы выполняются непрерывно, и не имеет значения, если это стек или куча? Я подозреваю, что процесс от I, где я называю вилку, огромен, и это является причиной тех процессов, которые я делаю результатом огромным. Я не знаю, как еще я мог бы пойти. скажем, процесс A огромен -> Я начинаю процесс B путем разветвления и исключения. B наследует область памяти A. Итак, теперь я делаю это -> A запускает C, который запускает inturn B также не поможет, поскольку C все еще наследует A ?. Я использовал vfork как альтернативу, которая тоже не помогла. Я действительно удивляюсь, почему.

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

ответ

2

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

В противном случае:

  1. Как вы измерения использования памяти? Некоторые методы не дают точных результатов.
  2. Убедитесь, что у вас нет утечек памяти. например с Valgrind на Linux x86.
  3. Вы можете попробовать запустить различные тестеры в одном процессе, как разные потоки или даже мультиплексироваться в одном потоке - поскольку сеть должна быть ограничивающим фактором?
  4. exec() уменьшит размер памяти процессов, так как новое выполнение получит новую карту памяти.
  5. Если вы не можете добавить физическую память, возможно, вы можете добавить swap, может быть, просто для тестирования?
1

Не технически отвечая на ваш вопрос, но и обеспечивает несколько альтернативных решений:

Если вы используете Linux вы рассматривали использование pktgen? Это гибкий инструмент для отправки UDP-пакетов из ядра так же быстро, как позволяет интерфейс.Это намного быстрее, чем инструмент пользовательского пространства.

oh и бесстыдная вилка. Я сделал multi-threaded network testing tool, который может быть использован для спама сети с UDP-пакетами. Он может работать в многопроцессорном режиме (используя fork) или многопоточном режиме (используя pthreads). В pthreads может использоваться меньше оперативной памяти, поэтому для вас может быть лучше. Если что-нибудь, возможно, стоит посмотреть на источник, поскольку я много лет улучшал этот код, и он смог создать достаточно пакетов для насыщения интерфейса 10 Гбит/с.

1

Что может случиться, так это то, что для вызова вилки в процессе A требуется значительное количество RAM + swap (если есть). Таким образом, когда вы вызываете fork() из этого процесса, ядро ​​должно резервировать достаточное количество ОЗУ и обменивать для дочернего процесса свою собственную копию (на самом деле запись на запись) доступной для записи частной памяти родительского процесса, а именно: стек и куча , Когда вы вызываете exec() из дочернего процесса, эта память больше не нужна, и ваш дочерний процесс может иметь собственный, меньший частный рабочий набор.

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

Во-вторых, попробуйте использовать параметры overcommit, которые позволят ядру зарезервировать больше памяти, чем есть на самом деле. Это/proc/sys/vm/overcommit *. Вы можете избавиться от использования overcommit, потому что вашим дочерним процессам требуется дополнительное пространство VM, пока они не вызовут exec, и не должны касаться дублированного адресного пространства родительского процесса.

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