С чего начать загрузку андроид

Создаем прошивку для Android своими руками. Загрузка операционной системы.

Как загружается система на ARM на примере android.

Начнем с простого упоминания, о том, что чип выполненный по архитектуре ARM — это система на чипе (SoC). То есть это полный компьютер, реализован- ный на одной микросхеме. На процессорах данной архитектуры изготавли- вается множество устройств (рутеры, свичи, встроенные компьютеры в телевизорах, игровые портативные консоли и т.д. и т.п.).

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

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

Итак, перейдем непосредственно к описанию загрузки данного типа устройств. Практически каждый ARM процессор имеет встроенную на чип flash-память, в которую помещается т.н. загрузчик. В случае отсутствия на чипе такой памяти, или неиспользования ее в качестве пространства для размещения загрузчика, чип обычно обращается для запуска этого загрузчика к NOR-flash по строго определенному адресу.

Самих загрузчиков существует несколько. Ряд из них — коммерческие. Но есть и загрузчик с открытым исходным кодом — u-boot. К сожалению, при открытости кода он содержит процессоро-зависимый код, поэтому без спецификаций процессора не может быть просто портирован (адаптирован) на процессор, который не имеет открытой документации.

Теперь опишем, что же обычно делает загрузчик после его запуска. Довольно прямая аналогия может быть проведена с BIOS компьютеров на базе процессоров х86 (те с основной массой персоналок). Загрузчик ARM при запуске точно так же выполняет рад низкоуровневых инициализаций аппаратной части устройства (оперативная память, хранилища данных, сетевой адаптер и т.д. и т.п.). После инициализации последовательного порта (обычно в формате RS232, но с уровнями 3.2 вольт) появляется возможность работы с ним через консоль инициализированной на этом порту.

Выглядит это так

Посредством этой консоли можно выполнить практически полную настройку или перенастройку нашей железки. Например, чтобы загрузить читый Linux, нам как минимум необходимо будет перенастроить строку параметров передаваемых ядру при загрузке (при умолчальной настройке на загрузку android). Так же там можно полностью работать и с разделами нанда — стирать, разбивать, изменять, защищать от записи и наоборот и т.д. и т.п. (дабы избежать дополнительных вопросов об изменении разделов нанда). Еще в консоли можно загружать и выполнять некоторый софт. Все настройки, выполненные в этой консоли, могут быть сохранены и использоваться как настройки по умолчанию при загрузке устройства.

Сделаем небольшое отступление. Кроме NOR-flash для размещения загрузчика, в ряде случаев, может быть использован NAND-flash или даже SD-card. Кроме того, возможно использование комбинаций этих типов флеш памяти в устройстве. Например загрузчик может быть размещен в NOR, а в качестве внутреннего накопителя (для размещения OS) NAND или SD и т.п.

Итак, мы включили железку. Она загрузила загрузчик. Загрузчик проинициализировал оборудование. По окончанию этой инициализации загрузчик выполняет следующую процедуру:

1 — считывание и размещение в оперативной памяти образа ядра и рамдиска — оба по строго определенным адресам (может быть настроено в командной строке u-boot).

2 — запуск ядра с правильной точки входа, с указанием ему, где брать внешний рамдиск (initrd) с корневой файловой системой и что использовать в качестве init.

Еще часть оперативной памяти отводится для устройств, требующих своей памяти, например для видеоядра. Теперь вы понимаете, куда девается некоторая часть заявленной производителем оперативной памяти устройства.

Дальнейшая загрузка мало отличается от загрузки Linux на обычном компьютере. Загрузившись, ядро выполняет указанный ему init (это просто еще одна программа). Настройка init осуществляется в файле init.rc, который расположен в рамдиске. В нем производится настройка переменных среды, монтирование дисковых устройств, запуск необходимых служб и т.д и т.п. По окончанию выполнения инструкций предзапуска из init.rc запускается собственно сам андроид. Вид запуска андроида обусловен параметром запуска ядра androidboot. Стандартный запуск андроид выполняется в целом посредством передачи параметров использования нужного рамдиска (в ramdisk.img) и параметра androidboot.normal. Для запуска режима восстановления, как правило, используется другой рамдиск, содержащий программу recovery (в recovery.img) и параметр ядра androidboot.recovery.

Как вариация ядра Linux для андроида могут быть собраны не с поддержкой initrd (корневая система на рамдиске), а с т.н. initramfs. В этом случае вся корневая файловая система будет расположена просто внутри ядра. В этом случае для режима восстановления нужно, как правило, второе ядро с корневой файловой системой содержащей программу recovery. И настройка загрузчика просто на загрузку и выполнение recovery ядра.

И как итог, простая схема:

Запуск процессора -> запуск загрузчика -> инициализация железа -> считывание из нанда ядра и рамдиска -> запуск ядра с использованием этого рамдиска -> выполнение программы init -> запуск собственно android.

Источник

Nurlandroid

Nurlan’s personal website

Show menu Hide menu

My name is Nurlan Nabiyev. I am passionate Android developer. This is my personal website with my portfolio of apps, posts and etc.

Contacts

Phone: +7 705 575 4828

Процесс загрузки ОС Android

Давайте узнаем о нюансах загрузки нашей любимой ОС и пройдем все этапы от BIOS-а до загрузки Android-приложения

На картинке ниже представлен краткий процесс загрузки ОС Android. Но как видно на картинке, процесс останавливается на запуске Launcher-а. Мы же пройдем весь процесс, вплоть до запуска обычного приложения.

Этап 1. Bootrom

Bootrom — это небольшой кусочек защищенной от записи флеш-памяти, встроенный в процессорный чип. Он содержит самый первый код, который выполняется процессором при его включении. Далее, он запускает BootLoader.

Этап 2. BootLoader

BootLoader выполняет первичный запуск специфичных настроек перед запуском ядра. То есть дословно, копирует файлы в рабочую память устройства и передает управление коду, расположенному в разделе boot, что по сути есть ядро Linux.

Этап 3. Ядро

Ядро запускает настройку кэша, защищенную память, планировщик задач и загружает драйверы. Когда ядро завершит настройку и запуск своих подсистем, он первым делом запустить корневой и самый главный процесс init(). Все процессы запускаемые после него являются дочерними.

Этап 4. init()

Процесс init() подключает директории /sys, /dev, /proc и запускает службы(daemon), которые указаны в файле init.rc. Например, Service Manager, Media Server. Формат init.rc достаточно простой и по сути представляет собой набор команд, разделенных на блоки. Каждый блок определяет стадию загрузки или, выражаясь языком разработчиков Android, действие. И наконец init() доходит до запуска среды выполнения Android путем запуска службы Zygote.

Этап 5. Среда выполнения Android

Zygote — ключевой компонент любой Android-системы, который ответственен за инициализацию, старт системных служб, запуск и остановку пользовательских приложений и многие другие задачи. Zygote запускается с помощью небольшого приложения /system/bin/app_process. Задача app_proccess — запустить виртуальную машину Art/Dalvik, код которой располагается в разделяемой библиотеке /system/lib/libandroid_runtime.so, а затем поверх нее запустить Zygote.

Читайте также:  Hk1 mini прошивка android 9

Когда все это будет сделано и Zygote получит управление, он начинает формирование среды исполнения Java-приложений с помощью загрузки всех Java-классов фреймворка (сейчас их более 2000).

Этап 6. system_server

Затем Zygote запускает system_server, включающий в себя большинство высокоуровневых (написанных на Java) системных сервисов, в том числе Window Manager, Status Bar, Package Manager и, что самое важное, Activity Manager, который в будущем будет ответственен за получение сигналов о старте и завершении приложений.

Этап 7. Activity Manager

После этого Zygote открывает сокет /dev/socket/zygote и уходит в сон, ожидая данные. В это время запущенный ранее Activity Manager посылает широковещательный интент Intent.CATEGORY_HOME, чтобы найти Launcher-приложение, отвечающее за формирование рабочего стола, и отдает его имя Zygote через сокет. Zygote, в свою очередь, форкается и запускает Launcher-приложение поверх виртуальной машины. Вуаля, у нас на экране появляется рабочий стол, найденный Activity Manager и запущенный Zygote, и статусная строка, запущенная system_server в рамках службы Status Bar.

Этап 8. Запуск «своего» приложения

А теперь давайте запустим свое приложение(например, Telegram), которое мы установили из Google Play Store. После тапа по иконке искомого приложения Launcher-приложение пошлет интент с именем этого приложения, его примет Activity Manager и передаст команду на старт приложения демону Zygote.

Когда Zygote получает запрос на старт приложения от Activity Manager, он не запускает новую виртуальную машину, а просто форкается, то есть копирует самого себя и затем запускает поверх полученной копии виртуальной машины нужное приложение. Копия ART/Dalvik VM создаёт главный поток приложения(MainThread).

Источник

Познавательно-практический экскурс в архитектуру Android

Содержание статьи

Тебя никогда не интересовало, как работают fastboot или ADB? Или почему смартфон под управлением Android практически невозможно превратить в кирпич? Или, может быть, ты давно хотел узнать, где кроется магия фреймворка Xposed и зачем нужны загрузочные скрипты /system/etc/init.d? А как насчет консоли восстановления (recovery)? Это часть Android или вещь в себе и почему для установки сторонней прошивки обычный рекавери не подходит? Ответы на все эти и многие другие вопросы ты найдешь в данной статье.

Как работает Android

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

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

Шаг первый. ABOOT и таблица разделов

Все начинается с первичного загрузчика. После включения питания система исполняет код загрузчика, записанного в постоянную память устройства. Затем он передает управление загрузчику aboot со встроенной поддержкой протокола fastboot, но производитель мобильного чипа или смартфона/планшета имеет право выбрать и любой другой загрузчик на его вкус. Например, компания Rockchip использует собственный, несовместимый с fastboot загрузчик, для перепрограммирования и управления которым приходится использовать проприетарные инструменты.

Протокол fastboot, в свою очередь, представляет собой систему управления загрузчиком с ПК, которая позволяет выполнять такие действия, как разлочка загрузчика, прошивка нового ядра и recovery, установка прошивки и многие другие. Смысл существования fastboot в том, чтобы иметь возможность восстановить смартфон в начальное состояние в ситуации, когда все остальные средства не работают. Fastboot останется на месте, даже если в результате экспериментов ты сотрешь со смартфона все разделы NAND-памяти, содержащие Android и recovery.

Получив управление, aboot проверяет таблицу разделов и передает управление ядру, прошитому в раздел с именем boot, после чего ядро извлекает в память RAM-образ из того же раздела и начинает загрузку либо Android, либо консоли восстановления. NAND-память в Android-устройствах поделена на шесть условно обязательных разделов:

  • boot — содержит ядро и RAM-диск, обычно имеет размер в районе 16 Мб;
  • recovery — консоль восстановления, состоит из ядра, набора консольных приложений и файла настроек, размер 16 Мб;
  • system — содержит Android, в современных девайсах имеет размер не менее 1 Гб;
  • cache — предназначен для хранения кешированных данных, также используется для сохранения прошивки в ходе OTA-обновления и поэтому имеет размер, сходный с размерами раздела system;
  • userdata — содержит настройки, приложения и данные пользователя, ему отводится все оставшееся пространство NAND-памяти;
  • misc — содержит флаг, определяющий, в каком режиме должна грузиться система: Android или recovery.

Кроме них, также могут существовать и другие разделы, однако общая разметка определяется еще на этапе проектирования смартфона и в случае aboot зашивается в код загрузчика. Это значит, что: 1) таблицу разделов нельзя убить, так как ее всегда можно восстановить с помощью команды fastboot oem format; 2) для изменения таблицы разделов придется разлочить и перепрошить загрузчик с новыми параметрами. Из этого правила, однако, бывают исключения. Например, загрузчик того же Rockchip хранит информацию о разделах в первом блоке NAND-памяти, так что для ее изменения перепрошивка загрузчика не нужна.

Часть кода загрузчика, определяющая таблицу разделов

Хакер #184. Современный фронтенд

Особенно интересен раздел misc. Существует предположение, что изначально он был создан для хранения различных настроек независимо от основной системы, но в данный момент используется только для одной цели: указать загрузчику, из какого раздела нужно грузить систему — boot или recovery. Эту возможность, в частности, использует приложение ROM Manager для автоматической перезагрузки системы в recovery с автоматической же установкой прошивки. На ее же основе построен механизм двойной загрузки Ubuntu Touch, которая прошивает загрузчик Ubuntu в recovery и позволяет управлять тем, какую систему грузить в следующий раз. Стер раздел misc — загружается Android, заполнил данными — загружается recovery. то есть Ubuntu Touch.

Шаг второй. Раздел boot

Если в разделе misc не стоит флаг загрузки в recovery, aboot передает управление коду, расположенному в разделе boot. Это не что иное, как ядро Linux; оно находится в начале раздела, а сразу за ним следует упакованный с помощью архиваторов cpio и gzip образ RAM-диска, содержащий необходимые для работы Android каталоги, систему инициализации init и другие инструменты. Никакой файловой системы на разделе boot нет, ядро и RAM-диск просто следуют друг за другом. Содержимое RAM-диска такое:

  • data — каталог для монтирования одноименного раздела;
  • dev — файлы устройств;
  • proc — сюда монтируется procfs;
  • res — набор изображений для charger (см. ниже);
  • sbin — набор подсобных утилит и демонов (adbd, например);
  • sys — сюда монтируется sysfs;
  • system — каталог для монтирования системного раздела;
  • charger — приложение для отображения процесса зарядки;
  • build.prop — системные настройки;
  • init — система инициализации;
  • init.rc — настройки системы инициализации;
  • ueventd.rc — настройки демона uventd, входящего в состав init.
Читайте также:  Клавиатура logitech для андроид

Это, если можно так выразиться, скелет системы: набор каталогов для подключения файловых систем из разделов NAND-памяти и система инициализации, которая займется всей остальной работой по загрузке системы. Центральный элемент здесь — приложение init и его конфиг init.rc, о которых во всех подробностях я расскажу позже. А пока хочу обратить внимание на файлы charger и ueventd.rc, а также каталоги sbin, proc и sys.

Файл charger — это небольшое приложение, единственная задача которого — вывести на экран значок батареи. Он не имеет никакого отношения к Android и используется тогда, когда устройство подключается к заряднику в выключенном состоянии. В этом случае загрузки Android не происходит, а система просто загружает ядро, подключает RAM-диск и запускает charger. Последний выводит на экран иконку батареи, изображение которой во всех возможных состояниях хранится в обычных PNG-файлах внутри каталога res.

Файл ueventd.rc представляет собой конфиг, определяющий, какие файлы устройств в каталоге sys должны быть созданы на этапе загрузки системы. В основанных на ядре Linux системах доступ к железу осуществляется через специальные файлы внутри каталога dev, а за их создание в Android отвечает демон ueventd, являющийся частью init. В нормальной ситуации он работает в автоматическом режиме, принимая команды на создание файлов от ядра, но некоторые файлы необходимо создавать самостоятельно. Они перечислены в ueventd.rc.

Каталог sbin в стоковом Android обычно не содержит ничего, кроме adbd, то есть демона ADB, который отвечает за отладку системы с ПК. Он запускается на раннем этапе загрузки ОС и позволяет выявить возможные проблемы на этапе инициализации ОС. В кастомных прошивках в этом каталоге можно найти кучу других файлов, например mke2fs, которая может потребоваться, если разделы необходимо переформатировать в ext3/4. Также модеры часто помещают туда BusyBox, с помощью которого можно вызвать сотни Linux-команд.

Каталог proc для Linux стандартен, на следующих этапах загрузки init подключит к нему procfs, виртуальную файловую систему, которая предоставляет доступ к информации обо всех процессах системы. К каталогу sys система подключит sysfs, открывающую доступ к информации о железе и его настройкам. С помощью sysfs можно, например, отправить устройство в сон или изменить используемый алгоритм энергосбережения.

Файл build.prop предназначен для хранения низкоуровневых настроек Android. Позже система обнулит эти настройки и перезапишет их значениями из недоступного пока файла system/build.prop.

Корневой раздел ТВ-приставки OUYA

Выносы из текста

  • Fastboot останется на месте, даже если в результате экспериментов ты сотрешь со смартфона содержимое всех разделов NAND-памяти
  • Раздел recovery полностью самодостаточен и содержит миниатюрную операционную систему, которая никак не связана с Android
  • Слегка изменив файл fstab, мы можем заставить init загрузить систему с карты памяти

Шаг второй, альтернативный. Раздел recovery

В том случае, если флаг загрузки recovery в разделе misc установлен или пользователь включил смартфон с зажатой клавишей уменьшения громкости, aboot передаст управление коду, расположенному в начале раздела recovery. Как и раздел boot, он содержит ядро и RAM-диск, который распаковывается в память и становится корнем файловой системы. Однако содержимое RAM-диска здесь несколько другое.

В отличие от раздела boot, выступающего в роли переходного звена между разными этапами загрузки ОС, раздел recovery полностью самодостаточен и содержит миниатюрную операционную систему, которая никак не связана с Android. У recovery свое ядро, свой набор приложений (команд) и свой интерфейс, позволяющий пользователю активировать служебные функции.

В стандартном (стоковом) recovery таких функций обычно всего три: установка подписанных ключом производителя смартфона прошивок, вайп и перезагрузка. В модифицированных сторонних recovery, таких как ClockworkMod и TWRP, функций гораздо больше. Они умеют форматировать файловые системы, устанавливать прошивки, подписанные любыми ключами (читай: кастомные), монтировать файловые системы на других разделах (в целях отладки ОС) и включают в себя поддержку скриптов, которая позволяет автоматизировать процесс прошивки и многие другие функции.

С помощью скриптов, например, можно сделать так, чтобы после загрузки recovery автоматически нашел на карте памяти нужные прошивки, установил их и перезагрузился в Android. Эта возможность используется инструментами ROM Manager, auto-flasher, а также механизмом автоматического обновления CyanogenMod и других прошивок.

Кастомные рекавери также поддерживают скрипты бэкапа, располагающиеся в каталоге /system/addon.d/. Перед прошивкой recovery проверяет наличие скриптов и выполняет их перед тем, как произвести прошивку. Благодаря таким скриптам gapps не исчезают после установки новой версии прошивки.

Команды fastboot

Чтобы получить доступ к fastboot, необходимо установить Android SDK, подключить смартфон к ПК с помощью кабеля и включить его, зажав обе кнопки громкости. После этого следует перейти в подкаталог platform-tools внутри SDK и запустить команду

На экран будет выведено имя устройства. Другие доступные команды:

  • fatsboot oem unlock — разлочка загрузчика на нексусах;
  • update файл.zip — установка прошивки;
  • flash boot boot.img — прошивка образа boot-раздела;
  • flash recovery recovery.img — прошивка образа раздела recovery;
  • flash system system.img — прошивка образа системы;
  • boot recovery.img — загрузка образа recovery без прошивки;
  • oem format — восстановление разрушенной таблицы разделов;
  • reboot — перезагрузка.

Шаг третий. Инициализация

Итак, получив управление, ядро подключает RAM-диск и по окончании инициализации всех своих подсистем и драйверов запускает процесс init, с которого начинается инициализация Android. Как я уже говорил, у init есть конфигурационный файл init.rc, из которого процесс узнает о том, что конкретно он должен сделать, чтобы поднять систему. В современных смартфонах этот конфиг имеет внушительную длину в несколько сот строк и к тому же снабжен прицепом из нескольких дочерних конфигов, которые подключаются к основному с помощью директивы import. Тем не менее его формат достаточно простой и по сути представляет собой набор команд, разделенных на блоки.

Каждый блок определяет стадию загрузки или, выражаясь языком разработчиков Android, действие. Блоки отделены друг от друга директивой on, за которой следует имя действия, например on early-init или on post-fs. Блок команд будет выполнен только в том случае, если сработает одноименный триггер. По мере загрузки init будет по очереди активировать триггеры early-init, init, early-fs, fs, post-fs, early-boot и boot, запуская таким образом соответствующие блоки команд.

Часть конфига init.rc из CyanogenMod

Если конфигурационный файл тянет за собой еще несколько конфигов, перечисленных в начале (а это почти всегда так), то одноименные блоки команд внутри них будут объединены с основным конфигом, так что при срабатывании триггера init выполнит команды из соответствующих блоков всех файлов. Это сделано для удобства формирования конфигурационных файлов для нескольких устройств, когда основной конфиг содержит общие для всех девайсов команды, а специфичные для каждого устройства записываются в отдельные файлы.

Наиболее примечательный из дополнительных конфигов носит имя initrc.имя_устройства.rc, где имя устройства определяется автоматически на основе содержимого системной переменной ro.hardware. Это платформенно-зависимый конфигурационный файл, который содержит блоки команд, специфичные для конкретного устройства. Кроме команд, отвечающих за тюнинг ядра, он также содержит примерно такую команду:

Она означает, что теперь init должен подключить все файловые системы, перечисленные в файле ./fstab.имя_устройства, который имеет следующую структуру:

Обычно в нем содержатся инструкции по подключению файловых систем из внутренних NAND-разделов к каталогам /system (ОС), /data (настройки приложений) и /cache (кешированные данные). Однако слегка изменив этот файл, мы можем заставить init загрузить систему с карты памяти. Для этого достаточно разбить карту памяти на три 4 раздела: 1 Гб / ext4, 2 Гб / ext4, 1 Гб / ext4 и оставшееся пространство fat32. Далее необходимо определить имена разделов карты памяти в каталоге /dev (для разных устройств они отличаются) и заменить ими оригинальные имена устройств в файле fstab.

Типичное содержимое файла fstab

В конце блока boot init, скорее всего, встретит команду class_start default, которая сообщит, что далее следует запустить все перечисленные в конфиге службы, имеющие отношение к классу default. Описание служб начинается с директивы service, за которой следует имя службы и команда, которая должна быть выполнена для ее запуска. В отличие от команд, перечисленных в блоках, службы должны работать все время, поэтому на протяжении всей жизни смартфона init будет висеть в фоне и следить за этим.

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

Команды init.rc

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

  • exec /путь/до/команды — запустить внешнюю команду;
  • ifup интерфейс — поднять сетевой интерфейс;
  • class_start имя_класса — запустить службы, относящиеся к указанному классу;
  • class_stop имя_класса — остановить службы;
  • insmod /путь/до/модуля — загрузить модуль ядра;
  • mount ФС устройство каталог — подключить файловую систему;
  • setprop имя значение — установить системную переменную;
  • start имя_службы — запустить указанную службу;
  • trigger имя — включить триггер (выполнить указанный блок команд);
  • write /путь/до/файла строка — записать строку в файл.

Шаг четвертый. Zygote и app_process

На определенном этапе загрузки init встретит в конце конфига примерно такой блок:

Это описание службы Zygote, ключевого компонента любой Android-системы, который ответственен за инициализацию, старт системных служб, запуск и остановку пользовательских приложений и многие другие задачи. Zygote запускается с помощью небольшого приложения /system/bin/app_process, что очень хорошо видно на приведенном выше куске конфига. Задача app_proccess — запустить виртуальную машину Dalvik, код которой располагается в разделяемой библиотеке /system/lib/libandroid_runtime.so, а затем поверх нее запустить Zygote.

Когда все это будет сделано и Zygote получит управление, он начинает формирование среды исполнения Java-приложений с помощью загрузки всех Java-классов фреймворка (сейчас их более 2000). Затем он запускает system_server, включающий в себя большинство высокоуровневых (написанных на Java) системных сервисов, в том числе Window Manager, Status Bar, Package Manager и, что самое важное, Activity Manager, который в будущем будет ответственен за получение сигналов о старте и завершении приложений.

После этого Zygote открывает сокет /dev/socket/zygote и уходит в сон, ожидая данные. В это время запущенный ранее Activity Manager посылает широковещательный интент Intent.CATEGORY_HOME, чтобы найти приложение, отвечающее за формирование рабочего стола, и отдает его имя Zygote через сокет. Последний, в свою очередь, форкается и запускает приложение поверх виртуальной машины. Вуаля, у нас на экране появляется рабочий стол, найденный Activity Manager и запущенный Zygote, и статусная строка, запущенная system_server в рамках службы Status Bar. После тапа по иконке рабочий стол пошлет интент с именем этого приложения, его примет Activity Manager и передаст команду на старт приложения демону Zygote

В терминологии Linux RAM-диск — это своего рода виртуальный жесткий диск, существующий только в оперативной памяти. На раннем этапе загрузки ядро извлекает содержимое диска из образа и подключает его как корневую файловую систему (rootfs).

В процессе загрузки Android отображает три разных загрузочных экрана: первый появляется сразу после нажатия кнопки питания и прошит в ядро Linux, второй отображается на ранних этапах инициализации и записан в файл /initlogo.rle (сегодня почти не используется), последний запускается с помощью приложения bootanimation и содержится в файле /system/media/bootanimation.zip.

Кроме стандартных триггеров, init позволяет определять собственные триггеры, которые могут срабатывать от самых разных событий: подключения устройства к USB, изменения состояния смартфона или изменения состояния системных переменных.

Кроме всего прочего, Activity Manager также занимается убийством фоновых приложений при нехватке памяти. Значения порогов свободной памяти содержатся в файле /sys/module/lowmemorykiller/parameters/minfree.

Все это может выглядеть несколько непонятно, но самое главное — запомнить три простые вещи:

  • Процесс запуска Android делится на две ключевые стадии: до Zygote и после. До старта Zygote система инициализирует низкоуровневые компоненты ОС. Это такие операции, как подключение (монтирование) файловых систем, запуск низкоуровневых служб (например rild, отвечающий за работу с GSM-модемом, SurfaceFlinger, управляющий тем, что изображено на экране, vold, управляющий подключенными файловыми системами). После запуска Zygote начинается инициализация исключительно Java-компонентов, которые составляют 80% операционной системы. Этим, в частности, пользуется известный фреймворк Xposed, который при установке подменяет app_process на собственную модифицированную версию, которая способна перехватывать вызовы любых Java-классов, подменяя их на любые другие. Именно поэтому у модулей Xposed такие широкие возможности по модификации внешнего вида и поведения Android. На самом деле они ничего не изменяют в системе, а просто заставляют ее использовать сторонние компоненты вместо своих.
  • Java-приложения никогда не запускаются «с нуля». Когда Zygote получает запрос на старт приложения от Activity Manager, он не запускает новую виртуальную машину, а просто форкается, то есть копирует самого себя и затем запускает поверх полученной копии виртуальной машины нужное приложение. Такой принцип работы позволяет, во-первых, свести расход памяти к минимуму, так как Linux при форке копирует память в режиме copy-on-write (новый процесс ссылается на память старого), а во-вторых, существенно ускорить запуск приложения: форк процесса происходит намного быстрее запуска новой виртуальной машины и загрузки нужных приложению Java-классов.
  • В Android повсеместно используются интенты. Для общения между собой компоненты Android никогда не применяют прямой вызов процедур и классов. Вместо этого используется система сообщений (интентов), которая, кроме высокого уровня безопасности, дает также множество других вкусностей, таких как, например, возможность вызвать приложение, ничего о нем не зная. Выше я уже писал, что для запуска рабочего стола системе достаточно послать интент Intent.CATEGORY_HOME, на который откликнется любое приложение, способное выполнять функцию лончера. Таким же образом работает кнопка «Поделиться», а также множество других компонентов системы.

Системные службы и потоки ядра

  • Официальная документация init.rc в исходниках Android: goo.gl/QciYVW
  • Описание формата файла /sys/module/lowmemorykiller/parameters/minfree: goo.gl/gKdGPT
  • Каталоговая структура Android: goo.gl/363Sq6
  • Описание фоновых служб: goo.gl/rtmGgf

Выводы

Во многом Android сильно отличается от других ОС, и с наскоку в нем не разобраться. Однако, если понять, как все работает, открываются просто безграничные возможности. В отличие от iOS и Windows Phone, операционка от гугла имеет очень гибкую архитектуру, которая позволяет серьезно менять ее поведение без необходимости писать код. В большинстве случаев достаточно подправить нужные конфиги и скрипты.

Евгений Зобнин

Редактор рубрики X-Mobile. По совместительству сисадмин. Большой фанат Linux, Plan 9, гаджетов и древних видеоигр.

Источник

Читайте также:  Android vkontakte com вход
Оцените статью