Яка різниця між vmalloc та kmalloc?


113

Я гуляв навколо і виявив, що більшість людей виступає за використання kmalloc, оскільки ви гарантовано отримуєте суміжні фізичні блоки пам'яті. Однак це, здається, kmallocможе не вдатися, якщо не вдасться знайти суміжний фізичний блок, який ви хочете.
Які переваги мати суміжний блок пам'яті? Зокрема, навіщо мені потрібно мати системний фізичний блок пам'яті в системному виклику ? Чи є якась причина, яку я не міг просто використати vmalloc?
Нарешті, якщо я мав би виділяти пам'ять під час обробки системного дзвінка, я повинен зазначити GFP_ATOMIC? Чи системний виклик виконується в атомному контексті?

GFP_ATOMIC
Виділення є пріоритетним і не спить. Це прапор для використання в обробниках переривань, нижній половині та інших ситуаціях, коли ви не можете спати.

GFP_KERNEL Це звичайне виділення і може заблокувати. Це прапор, який слід використовувати в контекстному коді процесу, коли він не може спати.


Хороша стаття про vmalloc та kmalloc http://learnlinuxconcepts.blogspot.in/2014/02/linux-memory-management.html
JIN007

4
Ця стаття вимагає дурниць на кшталт: "Як правило, 32-бітова архітектура має розмір сторінки 4 КБ, а 64-бітна архітектура має розмір сторінки 8 КБ". Я не повністю його прочитав, але не назвав би це "гарним" або навіть довіряв йому слово.
Олександро Санчес

1
Примітка (напівзалежно): vmallocшвидше з ядром 5.2 (Q2 2019)
VonC

Відповіді:


96

Вам потрібно потурбуватися про використання фізично суміжної пам'яті, якщо до буфера буде доступ DMA-пристрій на фізично адресованій шині (наприклад, PCI). Проблема полягає в тому, що багато системних викликів не мають можливості дізнатися, чи буде їх буфер врешті-решт переданий DMA-пристрою: як тільки ви передасте буфер в іншу підсистему ядра, ви дійсно не можете знати, куди він піде. Навіть якщо ядро ​​не використовує буфер для DMA сьогодні, майбутня розробка може це зробити.

vmalloc часто повільніше, ніж kmalloc, тому що, можливо, доведеться переставляти буферний простір у практично суміжний діапазон. kmalloc ніколи не відновлює, хоча якщо не викликається за допомогою GFP_ATOMIC, kmalloc може блокувати.

кмаллок обмежений розміром буфера, який він може забезпечити: 128 Кбайт *) . Якщо вам потрібен дійсно великий буфер, вам доведеться використовувати vmalloc або якийсь інший механізм, як резервування високої пам'яті під час завантаження.

*) Це стосувалося попередніх ядер. На останніх ядрах (я тестував це на 2.6.33.2), макс. Розмір одного кілометра має до 4 МБ! (Я написав про це досить детальний пост .) - kaiwan

Для системного дзвінка вам не потрібно передавати GFP_ATOMIC на kmalloc (), ви можете використовувати GFP_KERNEL. Ви не обробник переривань: код програми входить у контекст ядра за допомогою пастки, це не переривання.


1
Я думав, що системні дзвінки були введені, викликавши int $ 0x80? (тобто переривання)?
FreeMemory

2
int $ 0x80 - це програмне переривання, яке також називається пасткою. Під обробниками переривань мається на увазі апаратне переривання, наприклад, коли користувач натискає клавішу або здійснює переміщення.
Бранан

Системні виклики призначені для простору користувачів до переходів простору ядра ... kmalloc використовується лише в контексті ядра ??
AIB

3
@FreeMemory: int $ 0x80 є специфічним для x86, і тоді це також старий метод, заміщений sysenter / syscall (на x86).
jørgensen

18

Коротка відповідь: завантажте драйвери пристроїв Linux і прочитайте розділ про управління пам'яттю.

Серйозно, є багато тонких питань, пов’язаних із керуванням пам’яттю ядра, які вам потрібно зрозуміти - я витрачаю багато часу на налагодження з цим проблем.

vmalloc () дуже рідко використовується, тому що ядро ​​рідко використовує віртуальну пам'ять. kmalloc () - це те, що зазвичай використовується, але ви повинні знати, якими є наслідки різних прапорів, і вам потрібна стратегія для вирішення того, що відбувається, коли це не вдається - особливо якщо ви перебуваєте в обробці переривань, як вам запропонували.


1
"тому що ядро ​​рідко використовує віртуальну пам'ять", чому це все-таки?
Трей

Тому що ти, як правило, не хочеш блоку ядра, поки він чекає, коли ядро ​​поміняє пам'ять у дисковому сховищі чи поза ним ...
Майк Хайнц,

Ні, пам'ять ядра, виділену vmalloc, ніколи не змінюється. Заміняти можна лише пам'ять простору користувачів. Адресний простір ядра неможливо замінити, і vmalloc виділяє в адресному просторі ядра.
користувач2679859

13

На це дуже чітко відповідає розробка ядра Linux Роберт Лав (глава 12, стор. 244 у третьому виданні).

Так, фізично суміжну пам’ять у багатьох випадках не потрібно. Основна причина використання kmalloc більше, ніж vmalloc в ядрі, - продуктивність. У книзі пояснюється, що коли великі фрагменти пам’яті виділяються за допомогою vmalloc, ядро ​​має зіставити фізично непомітні шматки (сторінки) в єдину суміжну область віртуальної пам’яті. Оскільки пам'ять є практично суміжною і фізично не суміжною, до таблиці сторінок доведеться додати кілька віртуальних фізичних відображень адрес. І в гіршому випадку до таблиці сторінок буде додано (розмір буфера / розмір сторінки) кількість відображень.

Це також додає тиск на TLB (записи кеша, що зберігають останні віртуальне відображення фізичних адрес) під час доступу до цього буфера. Це може призвести до обмолоту .


11

kmalloc()& vmalloc()Функції простий інтерфейс для отримання пам'яті ядра в байтових шматки розміру.

  1. kmalloc()Функція гарантує , що сторінки фізично суміжні (і практично безперервні).

  2. vmalloc()Функція працює аналогічно тому kmalloc(), крім нього виділяє пам'ять, тільки практично безперервним і не обов'язково фізично безперервними.


4

Які переваги мати суміжний блок пам'яті? Зокрема, навіщо мені потрібно мати системний фізичний блок пам'яті в системному виклику? Чи є якась причина, що я не міг просто використовувати vmalloc?

З розділу "Я відчуваю себе щасливим" від Google vmalloc:

kmalloc є кращим способом, якщо вам не потрібні дуже великі площі. Проблема полягає в тому, що якщо ви хочете робити DMA з / на якийсь апаратний пристрій, вам потрібно буде використовувати kmalloc, і вам, ймовірно, знадобиться більший шматок. Рішення полягає в тому, щоб якнайшвидше розподілити пам'ять, перш ніж пам’ять роздробиться.


Бачите, я це читав, і це не має для мене сенсу. Я розумію, використовую kmalloc для великих площ; але для невеликих виділень, чому б не використовувати vmalloc, щоб уникнути фрагментації фізичної пам'яті?
FreeMemory

Тому що ви повинні довіряти ядру робити те, що найкраще; якщо він думає, що краще виділити одну частину, це зробить так. vmalloc - це лише тоді, коли ви абсолютно повинні мати суміжний шматок.
Темний Шикарі

Я думаю, це має сенс, але це здається контрінтуїтивним. kmalloc звучить так, як його слід використовувати, коли продуктивність викликає найбільше занепокоєння (тобто я не можу пошкодити диск IO). А як же GFP_ATOMIC?
FreeMemory

2

У 32-бітовій системі kmalloc () повертає логічну адресу ядра (хоча його віртуальну адресу), яка має пряме відображення (фактично з постійним зміщенням) на фізичну адресу. Це пряме відображення гарантує, що ми отримуємо постійний фізичний шматок оперативної пам’яті. Підходить для DMA, де ми даємо лише початковий покажчик і очікуємо наступного фізичного відображення після цього для нашої роботи.

vmalloc () повертає віртуальну адресу ядра, яка, в свою чергу, може не мати суцільного відображення на фізичній оперативній пам'яті. Корисно для великого розподілу пам’яті та у випадках, коли нам не байдуже, що пам'ять, виділена нашому процесу, є постійною також у фізичній оперативній пам’яті.


1

Однією з інших відмінностей кмalloc поверне логічну адресу (в іншому випадку ви вкажете GPF_HIGHMEM). Логічні адреси розміщуються у «низькій пам’яті» (у першому гігабайті фізичної пам’яті) і відображаються безпосередньо у фізичні адреси (використовуйте макрос __pa для перетворення). Ця властивість передбачає, що кілометрова пам'ять є суцільною пам'яттю.

З іншого боку, Vmalloc здатний повертати віртуальні адреси з "високої пам'яті". Ці адреси неможливо прямо перетворити у фізичні адреси (потрібно використовувати функцію virt_to_page).

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