ограничение памяти ядра Linux

12

У меня сбитая с толку проблема. У меня есть библиотека, которая использует sg для выполнения настраиваемых CDB. Есть несколько систем, которые обычно имеют проблемы с распределением памяти в sg . Обычно драйвер sg имеет жесткое ограничение около 4 МБ, но мы видим его на этих нескольких системах с ~ 2,3 МБ запросов. То есть CDB готовятся выделить для передачи 2,3 Мб. Здесь не должно быть никаких проблем: 2.3 <4.0.

Теперь о профиле машины. Это 64-битный процессор, но работает с 32-битным CentOS 6.0 (я их не собирал и не имею никакого отношения к этому решению). Версия ядра для этого дистрибутива CentOS - 2.6.32. У них 16 ГБ оперативной памяти.

Вот как выглядит использование памяти в системе (хотя, поскольку эта ошибка возникает во время автоматического тестирования, я еще не проверил, отражает ли это состояние, когда это errno возвращается из sg ).

top - 00:54:46 up 5 days, 22:05,  1 user,  load average: 0.00, 0.01, 0.21
Tasks: 297 total,   1 running, 296 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  15888480k total,  9460408k used,  6428072k free,   258280k buffers
Swap:  4194296k total,        0k used,  4194296k free,  8497424k cached

Я нашел эту статью из Linux Journal, которая посвящена распределению памяти в ядре. Статья датирована, но, похоже, относится к 2.6 (некоторые комментарии об авторе во главе). В статье упоминается, что ядро ​​ограничено примерно 1 ГБ памяти (хотя из текста не совсем ясно, если этот 1 ГБ каждый для физического и виртуального или общего объема). Мне интересно, если это точное утверждение для 2.6.32. В конечном счете, мне интересно, достигают ли эти системы этого предела.

Хотя это не совсем ответ на мою проблему, я задаюсь вопросом о правдивости претензии к 2.6.32. Итак, каков фактический предел памяти для ядра? Это может потребоваться для устранения неполадок. Любые другие предложения приветствуются. То, что делает это настолько озадачивающим, - то, что эти системы идентичны многим другим, которые не показывают ту же самую проблему.

Андрей Фаланга
источник

Ответы:

21

Ограничение в 1 ГБ для памяти ядра Linux в 32-разрядной системе является следствием 32-разрядной адресации, и это довольно жесткое ограничение. Это не невозможно изменить, но это есть по очень веской причине; изменение имеет последствия.

Давайте возьмем машину возврата к началу 1990-х годов, когда создавался Linux. В те дни у нас были споры о том, можно ли заставить Linux работать с 2 МБ ОЗУ или действительно нужно 4 МБ . Конечно, высококлассные снобы насмехались над нами, имея свои 16 чудовищных серверов MiB.

Какое отношение эта забавная маленькая виньетка имеет к чему-либо? В этом мире легко принимать решения о том, как разделить адресное пространство 4 ГиБ, которое вы получаете от простой 32-битной адресации. Некоторые операционные системы просто делят его пополам, обрабатывая верхний бит адреса как «флаг ядра»: адреса от 0 до 2 31 -1 очищают верхний бит и предназначены для кода пространства пользователя, а адреса от 2 31 до 2 32 - 1 был установлен верхний бит, и были для ядра. Вы можете просто посмотреть адрес и сказать: 0x80000000 и выше, это пространство ядра, иначе это пространство пользователя.

По мере того, как размеры памяти ПК приближались к этому пределу в 4 ГБ, такое простое разделение на 2/2 стало проблемой. Как пользовательское пространство, так и пространство ядра имели хорошие требования к большому объему оперативной памяти, но поскольку наша цель в том, чтобы иметь компьютер, как правило, для запуска пользовательских программ, а не для запуска ядер, ОС начали играть с разделением между пользователем и ядром. Раскол 3/1 является общим компромиссом.

Что касается вашего вопроса о физическом против виртуального, это на самом деле не имеет значения. Технически говоря, это ограничение виртуальной памяти, но это только потому, что Linux - это ОС на основе виртуальных машин. Установка 32 ГБ физической оперативной памяти ничего не изменит и не поможет swaponразделу подкачки 32 ГБ. Независимо от того, что вы делаете, 32-битное ядро ​​Linux никогда не сможет адресовать более 4 ГиБ одновременно.

(Да, я знаю о PAE . Теперь, когда 64-битные операционные системы наконец вступают во владение, я надеюсь, что мы можем начать забывать этот мерзкий взлом. Я не верю, что это может помочь вам в этом случае.)

Суть в том, что если вы работаете с лимитом виртуальной машины ядра 1 ГиБ, вы можете перестроить ядро ​​с разделением 2/2, но это напрямую влияет на программы в пространстве пользователя.

64-битный действительно правильный ответ.

Уоррен Янг
источник
1
Благодарю. Это рецензия великолепна. Я столкнулся с разделением 2/2, обычно используемым в Windows. В то время я узнал, что Linux использует 3/1 сплит. Хотелось бы подумать об этом, читая статью, думаю, я бы соединил точки. Так ... это звучит так, как будто я должен помнить об этом. Вероятно, недалек тот факт, что эти системы выходят за пределы, учитывая характер тестов. Большой вопрос, почему другие системы тоже не испытывают этого. Еще раз спасибо.
Эндрю Фаланга
1
@AndrewFalanga: На самом деле, современная Windows также использует нечеткое разделение 3/1 .
Уоррен Янг
1
Некоторые из нас смогли объединить память трех разных машин, унаследованных от SSC, чтобы получить 12 МБ сервер. Так много памяти, что мы могли делать все, что хотели ...
dmckee --- котенок экс-модератора
3
«Да, я знаю о модели сегментированной памяти x86 . Теперь, когда 32-битные ОС наконец-то вступают во владение, я надеюсь, что мы сможем забыть этот неприятный хак».
CVN
Между 32- и 64-разрядными вдвое больше удвоений, чем между 16- и 32-разрядными, что удваивает количество времени, которое мы должны откладывать, но при прочих равных условиях. Но все остальное не равно, что с закатом закона Мура. Мы получили два десятилетия от 32-разрядных вычислений x86. Мы могли бы получить века из 64-битных. Однопроходное считывание 2⁶⁴ байтов ОЗУ при сегодняшней пропускной способности DRAM займет около 30 лет . Откуда будет увеличиваться пропускная способность, чтобы мы могли приблизиться к 64-битному пределу?
Уоррен Янг
2

Я хочу добавить немного к отличному ответу Уоррена Янга , потому что на самом деле все хуже, чем он пишет.

Адресное пространство ядра в 1 ГБ дополнительно разделено на две части. 128 МБ для vmallocи 896 МБ для lowmem. Не берите в голову то, что это фактически означает. При распределении памяти код ядра должен выбрать, какой из них он хочет. Вы не можете просто получить память из того пула, где есть свободное место.

Если вы выберете vmalloc, вы ограничены 128 МБ. Теперь 1ГБ выглядит не так уж плохо ...

Если вы выбираете lowmem, вы ограничены до 896 МБ. Не так далеко от 1 ГБ, но в этом случае все выделения округляются до следующей степени 2. Таким образом, распределение 2,3 МБ фактически потребляет 4 МБ. Кроме того, вы не можете выделить более 4 МБ за один вызов при использовании lowmem.

64-битный действительно правильный ответ.

ugoren
источник
У меня есть вопрос, связанный с вашим ответом. Для этого пространства памяти с именем lowmem , откуда берется память от вызовов, таких как kmalloc и kzmalloc?
Андрей Фаланга
@AndrewFalanga, да, эти функции используют lowmem.
Угорен