обмеження пам'яті ядра 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 Гб оперативної пам’яті.

Ось як виглядає використання пам'яті в системі (хоча, оскільки ця помилка виникає під час автоматизованого тестування, я ще не перевіряв, чи відображає це стан, коли ця помилка повертається з 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 є ОС на базі VM. Встановлення фізичної оперативної пам’яті 32 Гб нічого не змінить, а також не допоможе swaponрозділити підрозділ 32 Гб. Незалежно від того, що ви робите, 32-розрядне ядро ​​Linux ніколи не зможе одночасно звертатися до більш ніж 4 Гб.

(Так, я знаю про PAE . Тепер, коли нарешті перейдуть 64-бітні ОС, я сподіваюся, що ми зможемо забути цей неприємний злом. Я не вірю, що він може допомогти вам у цьому випадку.)

Суть полягає в тому, що якщо ви користуєтесь обмеженням VM ядра 1 GiB, ви можете відновити ядро ​​з розділенням 2/2, але це безпосередньо впливає на програми користувальницького простору.

64-розрядна дійсно є правильною відповіддю.


1
Дякую. Ця запис велика. Я зіткнувся з розділом 2/2, який часто використовується в Windows. У той час я дізнався, що Linux використовував спліт 3/1. Я хотів би, щоб я про це подумав, читаючи статтю, я думаю, я би з'єднав крапки. Отже ... це звучить так, що я повинен мати це на увазі. Мабуть, далеко не досяжно, щоб думати, що ці системи досягають меж, враховуючи характер тестів. Велике питання полягає в тому, чому інші системи також цього не відчувають. Знову дякую.
Андрій Фаланга

1
@AndrewFalanga: Насправді сучасні Windows також використовують нечіткий розділ 3/1 .
Warren Young

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, ви обмежитеся 896MB. Не так далеко від 1 Гб, але в цьому випадку всі розподіли округляються до наступної потужності 2. Отже, розподіл 2,3 Мб фактично споживає 4 МБ. Крім того, ви не можете виділити більше 4 Мб в одному дзвінку під час використання lowmem.

64-розрядна дійсно є правильною відповіддю.


У мене питання, пов’язане з вашою відповіддю. Для цього простору пам’яті, який називається lowmem , звідки береться пам’ять від викликів, таких як kmalloc та kzmalloc?
Ендрю Фаланга

@AndrewFalanga, так, ці функції використовують lowmem.
ugoren
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.