Як я можу резервувати блок пам'яті з ядра Linux?


26

У мене є пристрій, якому потрібен блок пам'яті, який зарезервований виключно для нього, без втручання ОС. Чи є спосіб сказати BIOS або ОС, що блок пам'яті зарезервований, і він не повинен ним користуватися?

Я використовую цей пристрій на машині openSUSE.

Відповіді:


24

Те, що ви просите, називається DMA. Вам потрібно написати драйвер, щоб зберегти цю пам'ять.

Так, я розумію, ви сказали, що не хочете втручатися в ОС, і драйвер стає частиною ОС, але за відсутності застереження драйвера ядро ​​вважає, що вся пам'ять належить йому. (Якщо ви не скажете ядро ​​ігнорувати блок пам'яті, відповідно до відповіді Аарона.)

Розділ 15 (PDF) " Драйвери пристроїв Linux, 3 / e " Rubini, Corbet та Kroah-Hartmann охоплює DMA та пов'язані з ними теми.

Якщо ви хочете HTML-версії цього, я знайшов версію глави другого видання в іншому місці в Інтернеті. Будьте уважні, що друге видання вже більше десяти років, коли з'явилося, коли ядро ​​2.4 було новим. З тих днів було багато роботи над підсистемою управління пам’яттю ядра, тому воно вже не дуже добре застосовується.


За допомогою DMA я можу вибрати, які фізичні адреси використовувати? Чи дасть ядро ​​мені суміжний блок пам'яті? Чи гарантовано завжди буде доступно?
Натан Фелман

1
На ваші запитання відповідають на сторінці 442 PDF, на який я вказав.
Воррен Янг

25

Якщо ви хочете, щоб ОС повністю ігнорувала це, вам потрібно зробити отвір у пам'яті за допомогою "" memmap. Дивіться цю посилання . Наприклад, якщо ви хочете 512M на бар'єрі 2 Гб, ви можете поставити " memmap=512M$2G" в командному рядку ядра.

Вам потрібно буде перевірити, dmesgщоб знайти суміжний отвір для крадіжки, щоб ви не тупали на будь-яких пристроях; що характерно для вашої материнської плати + карт.

Це не рекомендований спосіб робити речі - див. Відповідь Уоррена Янга про те, як правильно це зробити (драйвери ядра + DMA). Я відповідаю на точне запитання, яке ви задали. Якщо ви плануєте зробити це для кінцевих користувачів, вони зненавидять вас, якщо ви їм це зробите ... повірте, це єдина причина, що я знав цю відповідь.


Редагувати: Якщо ви використовуєте grub2 w / grubby (напр., CentOS 7), вам потрібно переконатися, що ви виходите з $ . Там повинен бути один , \перш ніж $. Приклад:

$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"

1
Хоча ваша відповідь відповідає на моє запитання безпосередньо, відповідь Уорена здається кращим способом її вирішити. :-)
Натан Фелман

1
@WarrenYoung Я поняття не маю, що ти маєш з цим робити. Я б здогадався " uint8_t *ptr = 0x8000000" зі своїм прикладом? Або це може бути сегментарно ... Так, я справді не знаю. Знову я знав відповідь, тому що я був кінцевим користувачем погано розробленої PCI карти, де мені довелося вручну виділити буфер нижче позначки 4G, а потім сказати водієві, де цей простір; це може бути неможливим для користувача.
Аарон Д. Мараско

2
Тільки для посмішок я заглянув трохи глибше в це, і, здається, потрібно MMAP_FIXED | MMAP_ANON. Без користувальницького пристрою DMA, з яким тут можна грати, я не можу сказати, чи він насправді робить те, що хотів ОП, але мій ящик CentOS із задоволенням дав мені 8 МБ блок розміром 512 МБ, коли я сказав memmap=8M$512Mу GRUB. Він навіть не вимагає кореневого доступу, як я побоювався, що це може бути. Але навіть якщо це робить правильно, я все-таки думаю, що вам, мабуть, знадобиться драйвер, який може працювати з перебоями.
Воррен Янг

3
@ AaronD.Marasco: Ні, mmap()сторінки сторінок нульові, перш ніж код користувальницької програми отримує їх. Це робиться для безпеки, щоб дані не протікали з одного процесу в інший. Ще одна причина використовувати драйвер, оскільки вам може знадобитися зберегти вміст буфера DMA під час завантаження драйвера. Ну і до речі, довільно розташований mmap()виклик вдається навіть без memmapопції завантаження ядра, принаймні до тих пір, поки ніхто вже не використовує пам'ять, розташовану там, де ви запитали. Варіант завантаження без сумніву збільшує шанси на успіх, але це не є строго необхідним.
Warren Young

1
@ AaronD.Marasco Хм, добре. цікаво. дякую за те посилання, це добре прочитане.
Вудро Барлоу

5

Щоб зарезервувати блок пам'яті з ядра в Linux на базі ARM, ви також можете використовувати reserved-memoryвузол у файлі дерева (dts) вашого пристрою. У документації на ядро ​​(див. Тут ) є приклад:

memory {
    reg = <0x40000000 0x40000000>;
};

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* global autoconfigured region for contiguous allocations */
    linux,cma {
        compatible = "shared-dma-pool";
        reusable;
        size = <0x4000000>;
        alignment = <0x2000>;
        linux,cma-default;
    };

    display_reserved: framebuffer@78000000 {
        reg = <0x78000000 0x800000>;
    };

    multimedia_reserved: multimedia@77000000 {
        compatible = "acme,multimedia-memory";
        reg = <0x77000000 0x4000000>;
    };
};

0

Спочатку введіть цю команду, щоб перевірити поточні налаштування:

sysctl vm.min_free_kbytes

Щоб змінити встановлене значення, відредагуйте /etc/sysctl.conf. Шукайте рядок:

vm.min_free_kbytes=12888

Якщо його немає, створіть його (разом із бажаним значенням). Наступні значення прийнятні:

8192
12288
16384
20480

8М надзвичайно консервативний; він може зручно сидіти в 16М. Після зміни значення запустіть це, і перезавантаження не потрібно:

sudo sysctl -p

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