Ошибка дефрагментации RAM / OOM


11

Этот вопрос довольно длительный, поэтому я задам вопросы в верхней части, а затем расскажу, как перейти к вопросам:

  1. Разве (на основе Busybox) rm не выполнялся, потому что не было достаточно непрерывной оперативной памяти?
  2. Если так, есть ли легкий способ дефрагментации DMA - без перезапуска системы?
  3. Если нет, то чем это вызвано? Как я могу предотвратить это в будущем?

После того, как наша тестовая система работала довольно интенсивно в течение последних нескольких дней - я telnet'd в систему и проверил результаты теста. Когда я пришел удалить некоторые данные, система вернула командную строку (как если бы команда была выполнена правильно). Когда я пришел проверить каталог на наличие другого набора результатов, я увидел, что файл все еще существует (с помощью ls).

После этого я заметил, что все больше и больше моих команд оболочки работают не так, как ожидалось.

Я начну с вывода из dmesg после того, как rm не выполнится правильно:

Выделение длины 61440 из процесса 6821 (rm) не удалось

DMA на процессор:

CPU 0: hi: 0, btch: 1 usd: 0

Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 univictable: 6 dirty: 0 writeback: 0 unstable: 0 free: 821 slab: 353 сопоставлено: 0 pagetables: 0 bounce: 0

Свободное DMA: 3284 КБ, минимальное: 360 КБ, низкое: 448 КБ, высокое: 540 КБ, активный_анон: 0 КБ, inactive_anon: 0 КБ, активный_файл: 4 КБ, неактивный_файл: 0 КБ, необратимый: 24 КБ, присутствует: 8128 КБ, страниц: просмотрено: 0 все_ не подлежит возврату? нет

lowmem_reserve []: 0 0 0

DMA: 31 * 4 КБ 47 * 8 КБ 42 * 16 КБ 64 * 32 КБ 1 * 64 КБ 0 * 128 КБ 0 * 256 КБ 0 * 512 КБ 0 * 1024 КБ 0 * 2048 КБ 0 * 4096 КБ = 3284 КБ

Всего 14 страниц кэша страниц

Невозможно выделить ОЗУ для данных процесса, errno 12

Первоначально я думал, что не смог запустить программу в большей части непрерывной памяти. Это означает, что DMA был слишком фрагментирован, и мне нужно было бы найти способ заставить систему дефрагментировать память.

Затем я сделал быструю проверку математики и здравомыслия и понял, что программа должна была быть в состоянии работать в единственном слоте памяти объемом 64 КБ. Rm запрашивает 61440 байт (60 КБ).

Я сделал старый добрый «ручной дефрагментации» и перезагрузил систему. Когда я перезагрузил систему, я вывел / proc / buddyinfo:

Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0

Который я подозреваю карту:

  • 2 х 4 кБ
  • 8 х 8 кБ
  • 3 х 16 кБ
  • 12 х 32 кБ
  • 1 х 128 кБ
  • 1 х 512 кБ

Но если суммировать приведенный выше список значений, он не совпадает с выводом / proc / meminfo :

MemTotal:           6580 kB
MemFree:            3164 kB
Buffers:               0 kB
Cached:              728 kB
SwapCached:            0 kB
Active:              176 kB
Inactive:            524 kB
Active(anon):          0 kB
Inactive(anon):        0 kB
Active(file):        176 kB
Inactive(file):      524 kB`
Unevictable:           0 kB
Mlocked:               0 kB
MmapCopy:            844 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Slab:               1268 kB
SReclaimable:        196 kB
SUnreclaim:         1072 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        3288 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

Напомним, мои вопросы:

  1. Rm не выполнялся, потому что не было достаточно непрерывной оперативной памяти?
  2. Если так, есть ли легкий способ дефрагментации DMA - без перезапуска системы?
  3. Если нет, то чем это вызвано? Как я могу предотвратить это в будущем?

Я использую Lortronix XPort Pro (8 МБ, ОС Linux) под управлением uClinux версии 2.6.30. Оболочка в использовании является тихой.


Незначительный момент: вы пропустили 1 x 2048 кБ из вашего списка блоков памяти. Если вы включите это, то сумма составит 3192 кБ, что очень близко к 3164 кБ, перечисленным в / proc / meminfo.
Алекс Селби

Ответы:


11

На ваш вопрос 2 (дефрагментация памяти), цитата из https://www.kernel.org/doc/Documentation/sysctl/vm.txt :

compact_memory

Доступно только когда установлено CONFIG_COMPACTION. Когда в файл записывается 1, все зоны сжимаются так, что свободная память доступна в смежных блоках, где это возможно. Это может быть важно, например, при распределении огромных страниц, хотя процессы также будут непосредственно сжимать память по мере необходимости.

это означает, что следующая команда (выполняется с правами суперпользователя и если упомянутая выше опция ядра включена)

echo 1 > /proc/sys/vm/compact_memory

следует сообщить ядру, чтобы попытаться максимально дефрагментировать память. Помните, что, например, в некоторых версиях RHEL6 это может привести к сбою ядра ...


1
Спасибо, что потратили время, чтобы вернуться и прокомментировать старый вопрос!
OldTinfoil

7

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

Прежде чем я начну, я упомяну, что правильный термин, когда речь идет о «де-фрагментации» рабочей памяти, относится к «сжатию» рабочей памяти.

1. rm не выполнялся, потому что не было достаточно непрерывной оперативной памяти?

Я был прав в своем заключении - rm не выполнялся, потому что было недостаточно непрерывной оперативной памяти. Система собирала ОЗУ и фрагментировала ее, что делало ее невосстановимой.

2. Если так, есть ли легкий способ дефрагментации прямого доступа к памяти - без перезапуска системы?

Оказывается, нет способа сжать память, кроме перезапуска встроенной системы. В случае системы без MMU предотвращение - это название игры.

Часть меня размышляет, возможно ли взломать ядро ​​linux для эмуляции MMU в программном обеспечении. Я полагаю, если бы это было возможно, кто-то уже сделал бы это. Я не могу представить, что это совершенно новая концепция;)

3. Как я могу предотвратить это в будущем?

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

На первой итерации проекта мы использовали вызовы моего сценария оболочки для выполнения критических функций (таких как rm). Мы не видели необходимости заново изобретать колесо, если в этом не было необходимости.

Тем не менее, я бы рекомендовал по возможности избегать оболочки для системы без MMU -

( Вопрос , что произойдет, если вы выполните ls -la /path/to/directory/ | grep file-i-seek?)

( Ответ : запускается новый подпроцесс)

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


Спасибо, что нашли время вернуться и поделиться своими выводами.
Калеб

3
[Я понимаю, что это старый] Эмулировать MMU сложно ... Без MMU каждая программа напрямую использует физические адреса, которые появляются на шине памяти. Вы можете эмулировать один, но вам придется перехватывать каждый доступ к памяти (как это делает настоящий MMU). Производительность была бы ужасной. В качестве альтернативы вы можете использовать косвенные указатели (как это делал Mac OS Classic, называя их «ручками»), но тогда у вас будет совершенно сложный API, и очень сложный перед лицом упреждения (Mac OS Classic использует кооперативную многозадачность) ,
Дероберт

Спасибо, что вернулись и потратили время, чтобы написать этот ответ. Не знал, что MacOS classic сделал это.
OldTinfoil
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.