Как стать автором
Обновить
69.23
Surf
Создаём веб- и мобильные приложения

Как оживает смартфон: Android на старте

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров8.9K

Наши с вами телефоны включались бессчётное количество раз. Возможно, вы прямо сейчас запустили смартфон, чтобы прочитать эту статью. Ну а для тех, кто занимается разработкой, процесс включения устройств — обычная часть работы, которая повторяется десятки раз в день.

Что же на самом деле происходит в момент загрузки? Какие этапы преодолевает система от простого нажатия кнопки включения до появления интерфейса? И как устройство готовится к полноценной работе?

Вместе с Android-разработчиком Артёмом разберёмся, что скрывается под капотом Android и проследим процесс его запуска. Не пропустим ни шагу!

Для начала посмотрим, что эта система из себя представляет.

ОС Android — это операционная система, основанная на ядре Linux, что определяет её архитектуру и основные принципы. Как и в Linux, в Android принято выделять три условных уровняпользовательское пространство (User Space), пространство ядра (Kernel Space) и аппаратное обеспечение (Hardware). 

Пользовательское пространство — это область памяти, где размещаются приложения и программы верхнего уровня. В общем, то, с чем сталкивается рядовой пользователь. 

К аппаратному обеспечению относятся процессор, память и прочее. Эти два слоя друг о друге не знают и напрямую не взаимодействуют. За счёт этого обеспечивается абстрагирование работы с оборудованием для верхнеуровневых приложений, модульность, возможность запуска системы на разных устройствах с разными характеристиками. 

Всё это достигается благодаря пространству ядра, которое выступает в роли посредника между аппаратной частью и пользовательским пространством.

Но такой «посреднический» подход делает невозможным «прямой» запуск системы — без подготовительных этапов. Нужно, чтобы оборудование было проинициализировано и подготовлено, а ядро получило информацию о нём, чтобы впоследствии с ним же работать. 

Всё это ведёт нас к начальному этапу загрузки, который возьмёт на себя эти задачи.

Шаг 1. Boot ROM

Начальная инициализация и загрузка начинается с выполнения кода загрузочного ПЗУ — Boot ROM.

Это небольшой фрагмент памяти в процессорном чипе, который содержит тот самый инициализационный код. Задача этого кода — подготовить «железо» устройства к работе и выгрузить код во внешнюю оперативную память, когда все закончится. Этот код и загрузит нам ОС устройства.

Подготовка аппаратной части заключается в сбросе и запуске процессора, системной шины и внутренней оперативной памяти. А ещё — в выделении необходимого места для последующего запуска системы. 

После этого из выделенного для каждого устройства места — это местоположение определяется типом используемой в телефоне системы на кристалле (SoC) — во внешнюю оперативную память (DRAM) скопируется загрузчик. Он же продолжит процесс запуска.

Этот загрузчик называется Bootloader.

Шаг 2. Bootloader

Bootloader — это небольшая программа, записанная во встроенную память. Она завершает настройку оборудования, запуск ядра Linux и передачу управления загрузки системы.

У встроенной памяти ROM, инициализированной Boot ROM, небольшой объём. Обычно он не превышает нескольких сотен килобайт и используется для выполнения начальных этапов загрузки. 

Ядро Linux, даже в сжатом виде, занимает несколько мегабайт. При распаковке он значительно увеличивается, достигая десятков мегабайт. Получается, что объёма ROM недостаточно, поэтому для загрузки и работы ядра используется внешняя оперативная память.

Android, в частности, её ядро Linux, полагается на уже инициализированные устройства для корректного старта. Поэтому Bootloader должен подготовить их для ядра — чтобы оно могло сразу воспользоваться ими.

Это проходит в два этапа:

  1. Начальная загрузка программы (Initial Program Load).

Настройка внешней оперативной памяти и вторичная загрузка программы.

  1. Вторичная загрузка программы (Second Program Load).

Это загрузка драйверов дисплея, сенсоров, а также настройка файловой системы, виртуальной памяти (об устройстве памяти в Android мы поговорим дальше), сети и прочих систем.

Так, после того, как загрузчик найдёт ядро Linux, оно копируется во внешнюю оперативную память, после чего распаковывается и запускается.

Шаг 3. Ядро (Kernel)

Ядро в Linux можно сравнить с дирижёром в оркестре: оно координирует работу всех компонентов системы, обеспечивает взаимодействие между программами и любым аппаратным обеспечением. Оно управляет процессами, распределяет память, обрабатывает действия программ пользовательского пространства и контролирует доступ к аппаратной части. В общем, создаёт мост между «железом» и пространством пользователя. 

Ядро — своего рода интерфейс между аппаратной частью и процессами. Без него каждому приложению приходилось бы напрямую взаимодействовать с памятью, процессором и другими системами. Хаос в этом случае был бы обеспечен. 

Хотя у ядра Android и Linux есть ряд различий, в контексте запуска системы ядро Android запускается аналогично ядру Linux и действует точно так же. 

До запуска основного процесса, происходит предварительная настройка: монтируется файловая система, загружаются драйверы.

Ядро Linux отвечает за управление ресурсами и аппаратным обеспечением, но не запускает приложения и пользовательские сервисы напрямую. Для этого нужно перейти в пространство пользователя.

Чтобы перейти из пространства ядра в пространство пользователя после подготовительных действий, ядро ищет и запускает корневой — самый главный — процесс в системе — init(). Именно он управляет запуском системных сервисов и приложений.

Шаг 4. init

Процесс init служит «архитектором» пользовательской среды: подготавливая ее, он запускает системные сервисы и демоны, а затем передает управление рабочим процессам и приложениям. 

Прежде всего init готовит файловую систему к работе, монтируя разделы /sys, /dev, /proc. Они нужны для виртуальной памяти.

Виртуальная память — это механизм, который нужен, чтобы память устройства использовалась наиболее эффективно и безопасно при работе множества процессов. Для этого используется механизм пагинации (Paging). Пространство виртуальной памяти разбивается на множество блоков-страниц и каждому процессу выдаётся нужное число страниц, благодаря чему не возникает конфликтов.

Файловая система готова для запуска системных служб и конфигурации. Теперь init-процессу нужно получить информацию о настройке параметров ядра и запуске служб. Она лежит в файле init.rc, который находится в system/core/rootdir. В нём расположен список команд, которые нужно выполнить. 

В процессе будут запущены:

  • Service Manager  для управления системными службами через механизм Binder;

  • Media Server для воспроизведения аудио и видео, работы с камерой и другие сервисы.

И, наконец, в самом конце init доходит до запуска службы Zygote.

Шаг 5. Zygote

Zygote играет важную роль в запуске приложений и создании среды их исполнения. Название Zygote (зигота) довольно символично — вспомним курс школьной биологии. Зигота в биологии — основа для создания организма. А процесс Zygote — основа для создания процессов приложений в Android.

Zygote запускается на ранних этапах работы системы с помощью приложения /system/bin/app_process. Оно инициализирует виртуальную машину ART или Dalvik (в зависимости от версии Android), загружая её код из библиотеки /system/lib/libandroid_runtime.so

Но зачем?

Обычно в Java-программе для каждого приложения создаётся отдельный экземпляр виртуальной машины JVM. Он загружает и инициализирует все классы и библиотеки с нуля. 

Но для Android такой подход применить нельзя. Если бы Android создавал отдельную виртуальную машину для каждого приложения, это привело бы:

  • к высокому потреблению памяти — многие виртуальные машины дублировали бы одни и те же библиотеки и классы;

  • к длительному запуску — процесс загрузки и инициализации классов требует значительных затрат времени, а эти операции повторялись бы для каждого приложения.

Эту проблему и решает Zygote:

  • она заранее загружает и инициализирует основные классы и ресурсы Android SDK, которые понадобятся приложениям. Эти классы впоследствии будут доступны всем приложениям;

  • когда будет запускаться новое приложение, новая виртуальная машина не создастся. Вместо этого, для создания нового процесса для запускаемого приложения Zygote скопирует в него своё состояние с помощью системного вызова fork(). Созданный таким образом процесс наследует загруженные классы и ресурсы;

  • классы, загруженные Zygote, хранятся в памяти в виде read-only, что позволяет нескольким процессам одновременно обращаться к ним без дублирования.

Таким образом, с помощью Zygote формируется среда исполнения Java-приложений путем загрузки всех Java-классов для фреймворка.

Шаг 6. System Server

Первый процесс, создаваемый путем fork() от Zygote, — процесс, в котором запускается System Server.

Это, по сути, завершающий этап загрузки системы. Именно служба System Server запускает большинство высокоуровневых сервисов, каждый из которых отвечает за часть функциональности Android. И без которых работа приложений была бы невозможна.

  1. Запускается Activity Manager. Он отвечает за запуск, остановку и завершение приложений и обеспечивает взаимодействие между ними.

После его запуска отправится широковещательный интент Intent.CATEGORY_HOME. Он поможет определить Launcher-приложение, которое отвечает за отображение рабочего стола.

Launcher-приложение – это специальное приложение, у которого в манифесте есть соответствующий фильтр.

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name = "android.intent.category.HOME" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

Когда подходящее приложение обнаружено, Zygote создаёт новый процесс и запускает в нём Launcher-приложение. 

В результате на экране появляется рабочий стол. Параллельно с этим System Server запускает службу Status Bar, которая отвечает за отображение статусной строки, и другие службы.

  1. Запускается Window Manager. Он управляет всеми окнами на экране. Под окнами в данном случае понимаются базовые компоненты, используемые для отображения интерфейса приложения (или системы).

Так, когда в активности вызывается метод setContentView(), макет этой активности прикрепляется к соответствующему ей окну. Его дальнейшим размещением и отображением занимается Window Manager. 

Если на устройстве открыто несколько приложений, Window Manager отображает окно активного приложения поверх других. Осуществляется это за счет управлением z-упорядоченной системы окон.

Z в данном случае означает глубину — как в трехмерной системе координат. Z-список определяет, какие окна располагаются поверх других на экране. Насколько низко или высоко будет расположено окно, определяется порядком его добавления, а также наличием или отсутствием фокуса.

  1. Power Manager управляет энергопотреблением устройства. Помимо работы с яркостью экрана, ее автоматической регулировки, контроля за потреблением энергии Wi-Fi, Bluetooth и геолокации, Power Manager работает с wavelock-ами

И вот, когда основные системные службы запущены, базовые функции системы готовы.

Тогда система отправляет широковещательный интент Intent.ACTION_BOOT_COMPLETED. Это сообщение сигнализирует приложениям и системным компонентам, которые подписаны на него, что загрузка завершена. 

Обрабатывать его может и пользовательское приложение, для этого достаточно разрешения:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

И интент-фильтр такого вида:

<intent-filter> 
<action android:name="android.intent.action.BOOT_COMPLETED" /> 
</intent-filter>

На этом процесс загрузки ОС Android можно считать завершенным.

Вот такой, поистине колоссальный, объём работы скрывается за привычным интерфейсом, который мы видим каждый день на экране Android-устройств.

Больше полезного про Android — в Telegram-канале Surf Mobile Team

Кейсы и лучшие практики в области системной и бизнес-аналитики, новости, вакансии и стажировки Surf. Присоединяйтесь!

Теги:
Хабы:
Всего голосов 20: ↑19 и ↓1+21
Комментарии2

Публикации

Информация

Сайт
surf.ru
Дата регистрации
Дата основания
Численность
201–500 человек
Местоположение
Россия