Разработка
Как Android управляет маленькой памятью: Kswapd и LMK
В этой статье мы рассмотрим, как Android распределяет память и реагирует на ситуации с нехваткой памяти.
Будучи мобильной операционной системой, Android приходится иметь дело с ограниченными ресурсами памяти. ОС тщательно следит за использованием памяти и принимает меры по ее освобождению, когда ее становится мало.
В этой статье мы рассмотрим, как Android распределяет память и реагирует на ситуации с нехваткой памяти.
Платформа Android работает на основе принципа, что свободная память — это зря потраченная память.
Учитывая это правило, ОС Android всегда старается выделить всю доступную память.
Это очень полезная и удивительная техника. Так как система может хранить в памяти недавно использовавшиеся приложения, и пользователь может быстро переключиться на них без задержек при запуске.
В любом случае, память нужна системе, и Android OS использует ее эффективно. Но что делать, если вся память занята? Как открыть больше приложений? Не волнуйтесь! Android справляется и с этим!
Он использует две важные концепции: Kswapd и LMK (Low Memory Killer). Но сначала давайте разберемся в основах.
Типы памяти
Устройства Android содержат три различных типа памяти: RAM, zRAM и хранилище.
- RAM, оперативная память: самая быстрая, но ограниченная память.
- zRAM: раздел оперативной памяти, используемый для пространства подкачки. Все сжимается при помещении в zRAM, а затем распаковывается при копировании из zRAM.
- Хранилище: содержит все постоянные данные.
Страницы
Оперативная память разбита на страницы. Обычно каждая страница занимает 4 КБ памяти.
Страница (часть оперативной памяти) может считаться либо «используемой», либо «неиспользуемой» (свободной).
Используемая страница может быть использована либо известным нам процессом (допустим, мы знаем, что процесс A использует страницу номер 154), либо каким-то анонимным процессом (мы не знаем, кто использует страницу).
Страница, используемая известным процессом, называется «кэш».
- Частный (Private ) кэш: принадлежит одному процессу.
- Общий (Shared) кэш: используется несколькими процессами (пример: сервисы Google, такие как определение местоположения, могут использоваться несколькими процессами).
Кэш может быть «чистым» или «грязным».
- Чистый (Clean): неизмененная копия некоторого файла, который уже присутствует в хранилище (может быть удалена и снова взята из хранилища).
- Грязный (Dirty): измененная копия файла (измененные данные будут потеряны при удалении).
Но что делать, если эти страницы почти все использованы? Android придется как-то справляться с ними.
Управление памятью
В Android есть два основных механизма для решения проблем с нехваткой памяти: демон подкачки ядра и убийца при низкой памяти.
Как вы, наверное, знаете, Android работает на ядре Linux, и это ядро Linux поддерживает низкий и высокий пороги свободной памяти.
Kswapd: демон подкачки ядра
kswapd
возвращает чистые страницы, удаляя их.
- Он становится активным, когда свободная память устройства падает ниже порогового значения.
- Он останавливается, когда свободная память достигает высокого порога.
- Чистая страница удаляется и может быть легко скопирована обратно в оперативную память из хранилища, если какой-либо процесс потребует ее (так называемая подкачка по требованию).
Если этого недостаточно, kswapd
также может перемещать кэшированные приватные грязные страницы и анонимные грязные страницы в zRAM, где они сжимаются. И если какой-либо процесс потребует их, то мы сможем распаковать и вернуть их обратно.
LMK: убийца низкой памяти
Если kswapdc
не мог освободить достаточно памяти, необходимой системе, ядро начинает убивать процессы, чтобы освободить больше памяти, используя lmk (low-memory killer).
Чтобы решить, какой процесс убить, LMK использует показатель «нехватки памяти» под названием oom_adj_score
для определения приоритета запущенных процессов.
Высокие оценки для закрытия — вверху, низкие — внизу.
- Фоновые приложения: наименее важное фоновое приложение будет закрыто первым.
- Предыдущее приложение: Наиболее часто используемое фоновое приложение. Имеет более высокий приоритет (более низкий балл) по сравнению с другими фоновыми приложениями.
- Приложение домашнего экрана: Лаунчер. Убийство этого приложения приведет к исчезновению обоев.
- Службы: Запускаются приложениями и могут включать синхронизацию или загрузку в облако.
- Видимые приложения: Приложения, которые частично видны или выполняют фоновые задачи. Например, воспроизведение музыки.
- Приложение переднего плана: Приложение, которое используется в данный момент. Убийство приложения переднего плана выглядит как сбой приложения.
- Постоянные (службы): Основные службы устройства, такие как телефония, Bluetooth, Wi-Fi.
- Система: Системные процессы. При уничтожении этих процессов может возникнуть впечатление, что телефон перезагружается.
- Нативные (Native): Процессы очень низкого уровня, используемые системой (например, kswapd).
Чтобы убить приложение, ядро должно знать конкретные страницы, которые используются процессом, это называется «след памяти».
Также могут существовать общие страницы памяти, верно? Я уже объяснял это выше.
При определении объема памяти, используемой приложением, система должна учитывать общие страницы.
Есть три способа определения:
- Резидентный (Resident Set Size, RSS): Все страницы: Shared + Non-Shared.
- Пропорциональный (Proportional Set Size, PSS): Не разделенные страницы + равномерное распределение разделяемых страниц (например, если три процесса совместно используют 3 МБ, каждый процесс получает 1 МБ в PSS) (используется именно этот способ).
- Уникальный (Unique Set Size, USS): Только не разделенные страницы.
PSS — это то, что используется ОС. Вычисление PSS занимает много времени, поскольку системе необходимо определить, какие страницы и сколько процессов их совместно используют.
После этого в памяти обязательно появится свободное место для запуска нового приложения.
Ищете видеообъяснение? Посмотрите это:
-
Видео и подкасты для разработчиков4 недели назад
SwiftUI: алхимия приложений — превращаем идеи в реальность
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.3
-
Магазины приложений2 недели назад
Приложение Hot Tub появится на iOS в EC
-
Разработка3 недели назад
Смешивание цветов в SwiftUI