Memory management в ядрі Linux. Семінар в Яндексі

    Привіт! Мене звати Роман Гущин. У Яндексі я займаюся ядром Linux. Некторих час тому я провів для системних адміністраторів семінар, присвячений загальному опису підсистеми управління пам'яттю в Linux, а також деяким проблемам, з якими ми стикалися, і методів їх вирішення. Велика частина інформації описує «ванільне» ядро ​​Linux (3.10), але деяка частина специфічна для ядра, що використовується в Яндексі. Цілком можливо, семінар виявиться цікавий не тільки системним адміністраторам, а й усім, хто хоче дізнатися, як в Linux влаштована робота з пам'яттю.
 
  
Основні теми, порушені на семінарі:
 
     
  • Завдання і компоненти підсистеми управління пам'яттю;
  •  
  • Апаратні можливості платформи x86_64;
  •  
  • Як описується в ядрі фізична і віртуальна пам'ять;
  •  
  • API підсистеми управління пам'яттю;
  •  
  • Вивільнення раніше зайнятої пам'яті;
  •  
  • Інструменти моніторингу;
  •  
  • Memory Cgroups;
  •  
  • Compaction — дефрагментація фізичної пам'яті.
  •  
Під катом ви знайдете більш докладний план доповіді з розкриттям основних понять і принципів.
 
 Завдання підсистеми управління пам'яттю і компоненти, з яких вона складається
Основне завдання підсистеми — виділення фізичної пам'яті ядру і userspace-процесам, а також вивільнення і перерозподіл в тих випадках, коли вся пам'ять зайнята.
 
Основні компоненти:
 
     
  • Buddy allocator займається менеджментом пулу вільної пам'яті.
  •  
  • Page replacent («LRU» reclaim model) вирішує, у коли відібрати пам'ять, коли закінчилася вільна.
  •  
  • PTE management — блок управління таблицями трансляції.
  •  
  • Slub kernel allocator — внутрішній ядерний аллокатор.
  •  
  • та ін
  •  
 Апаратні можливості платформи x86_64
Схема NUMA увазі, що до кожного фізичній процесору приєднаний деякий обсяг пам'яті, до якого він може звертатися найшвидше. Звернення до ділянок пам'яті інших процесорів відбувається значно повільніше.
 
 Як описується в ядрі фізична і віртуальна пам'ять?
Фізична пам'ять в ядрі описується трьома структурами: ноди (pg_data_t), зони (struct zone), сторінки (struct page). Віртуальна пам'ять у кожного процесу своя і описується за допомогою структури struct mm_struct. Вони, в свою чергу, діляться на регіони (struct vm_area_struct).
 
 API підсистеми управління пам'яттю
Ядро взаємодіє з підсистемою memory management за допомогою таких функццій функцій, як __ get_free_page (), kmalloc (), kfree (), vmalloc (). Вони відповідають за виділення вільних сторінок, великих і малих ділянок пам'яті, а також їх вивільнення. Існує ціле сімейство подібних функцій, що відрізняються невеликими особливостями, наприклад, чи буде занулити область при вивільненні.
 
Користувальницькі програми взаємодіють з mm-підсистемою за допомогою функцій mmap (), munmap (), brk (), mlock (), munlock (). Також є функції posix_fadvice () і madvice (), які можуть давати ядру «Поради». Але враховувати їх у своїх евристиках воно строго говоря не зобов'язане.
 
 Вивільнення раніше зайнятої пам'яті (memory reclaim)
Система завжди намагається підтримувати певний обсяг вільної пам'яті (free pool). Таким чином, пам'ять виділяється набагато швидше, тому що не доводиться вивільняти її в той момент, коли вона вже дійсно потрібна.
 
Ті сторінки в пам'яті, які використовуються постійно (системні бібліотеки і т.п), називаються working set. Витіснення їх з пам'яті призводить до уповільнення роботи всієї системи. Загальна швидкість споживання пам'яті в системі називається memory pressure. Ця величина може дуже сильно коливатися залежно від того, наскільки завантажена система.
 
Всю незайняту ядром пам'ять в системі можна поділити на дві частини: анонімна пам'ять і файлова. Відрізняються вони тим, що про першу ми точно знаємо, що кожен її шматок відповідає якомусь файлу, і його можна туди скинути.
 
 Модель «LRU»
LRU розшифровується як list recently used. Це абстракція, яка пропонує викидати сторінки, до яких ми найдовше не зверталися. Реалізувати її в Linux повноцінно неможливо, тому все що нам відомо — чи було коли-небудь звернення до тієї чи іншої сторінці. Щоб якось відстежувати частоту запитів сторінок використовуються списки active, inactive і unevictable. В останньому знаходяться залоченние користувачем сторінки, які не будуть викидатися з пам'яті ні за яких умов.
 
Існують чіткі правила переміщення між списками inactive і active. Під впливом memory pressure, сторінки з неактивного списку можуть бути або викинуті з пам'яті, або перейти в активний. Сторінки з активного списку переміщаються в неактивний, якщо до них давно не було звернень.
 
 Інструменти моніторингу
Утиліта top демонструє статистику споживання пам'яті в системі. Програмка vmtouch — показує яка частина певного файлу знаходиться в пам'яті. Вичерпну інформацію щодо кількості файлових, активних і неактивних сторінок можна знайти в / proc / vmstat. Статистика buddy allocator є в / proc / buddyinfo, а статистика slub allocator, відповідно, в / proc / slabinfo. Часто буває корисно подивитися на perf top, де відмінно видно всі проблеми з фрагментацією.
 
 Memory cgroups
Сігруппи зародилися з бажання виділити групу з кількох процесів, об'єднати їх логічно і обмежити їх сумарне споживання пам'яті визначеним. При цьому, якщо вони досягнуть свого ліміту, пам'ять повинна вивільнятися саме з виділеного їм обсягу. У цьому випадку потрібно звільнити пам'ять, що належить саме цієї сігруппе (це називається target reclaim). Якщо в системі просто закінчилася пам'ять і потрібно поповнити free pool — це називається global reclaim. C точки зору аккаунтинга кожна сторінка належить тільки одній сігруппе: тієї, яка її перший прочитала.
 
 Compaction
Compaction — це механізм дефрагментації фізичної пам'яті. Механізм цей був досить довго зламаний, приблизно з версії 3.3 до версії 3.7. Це проявлялося в тому, що на деяких машинах з потужним фрагментуються моментом через два тижні роботи всі процесори були зайняті виключно compaction і ніякого корисної дії не скоювали.
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.