Как происходит fork процесса в Android
Что проверяют
Знаете ли вы, откуда берётся процесс приложения и почему Android запускает его быстро: через Zygote и копирование при записи. Следом часто спрашивают, почему в момент fork у Zygote должен остаться один поток и что делает system_server.
Как отвечать
Схема запуска:
- init и Zygote: при загрузке
initстартует процесс Zygote (бинарьapp_process). Он поднимает ART, заранее загружает тысячи классов фреймворка и общие ресурсы, затем слушает сокет и ждёт команд; - system_server: одним из первых потомков Zygote становится
system_server, в нём живутActivityManagerService,PackageManagerServiceи другие системные сервисы; - запрос на процесс: когда нужно запустить компонент приложения, а процесса ещё нет,
ActivityManagerServiceчерезProcess.startотправляет в сокет Zygote параметры: uid, gid, SELinux-контекст, класс точки входа; - fork и специализация: Zygote вызывает
fork(), потомок сбрасывает привилегии до uid приложения, применяет SELinux-контекст и seccomp-фильтр, а затем вызываетActivityThread.main(), где запускается главныйLooper; - copy-on-write: страницы памяти с предзагруженными классами и ресурсами остаются общими для всех приложений, пока их никто не меняет. Так старт дешевле, а память экономится.
Тонкость про потоки: fork() копирует только вызвавший поток. Поэтому Zygote перед форком останавливает свои служебные демоны (сборщик мусора, финализаторы) и форкается однопоточным, иначе потомок получил бы захваченные мьютексы без владельцев. На устройствах с поддержкой 32-битных приложений обычно работают две Zygote: для 64-битных и для 32-битных процессов.
Где спотыкаются
Путают процессы и потоки: отвечают про AsyncTask или HandlerThread. Это многопоточность внутри процесса, к fork отношения не имеет, а AsyncTask к тому же давно объявлен устаревшим.
Говорят, что fork копирует всю память родителя. На деле копируются таблицы страниц, а физическая копия страницы появляется только при записи в неё.
Думают, что приложение само решает, когда создать свой процесс. Решение принимает system_server, а приложение лишь запрашивает компонент через Intent.