- Русские Блоги
- [Boot] Глава по инициализации запуска системы Android
- I. Обзор
- 1.1 main
- 1.2 система логов
- 1.3 console_init_action
- 1.4 restart_processes
- Два, обработка сигналов
- 2.1 signal_handler_init
- 2.2 reap_any_outstanding_children
- 2.3 register_epoll_handler
- Три, синтаксис файла rc
- 3.1 Action
- 3.2 Service
- 3.3 Command
- 3.4 Options
- В-четвертых, запустите службу
- 4.1 Последовательность запуска
- 4.2 Запуск службы (Zygote)
- 4.3 Перезапуск службы
- Пять, атрибутная служба
- 5.1 property_init
- 5.2 start_property_service
- 5.3 handle_property_set_fd
- 5.4 handle_property_set
- Шесть, резюме
- Основы безопасности операционной системы Android. Native user space, ч.1
- Вступление
- Список статей
- Что подразумевается под Native user space
- Файловая система Android
- Процесс загрузки Android
- Заключение
- Ссылки
Русские Блоги
[Boot] Глава по инициализации запуска системы Android
На основе анализа исходного кода Android 6.0 проанализируйте рабочее содержимое процесса инициализации с номером процесса 1 в процессе запуска Android.
I. Обзор
Процесс init — это первый процесс в пользовательском пространстве в системе Linux, и его номер фиксирован на 1. После запуска ядра процесс init запускается в пользовательском пространстве, и вызывается метод main () в init для выполнения обязанностей процесса init. Функция процесса init разделена на 4 части:
- Разберите и запустите все файлы, связанные с init.rc
- В соответствии с файлом rc сгенерируйте соответствующий узел драйвера устройства
- Обработка завершения дочернего процесса (метод сигнала)
- Обеспечить функцию службы атрибутов
Начнем с метода main ().
1.1 main
После завершения выполнения процесса init он переходит в состояние ожидания цикла epoll_wait.
1.2 система логов
В настоящее время система журналов Android не запущена.Если используется система журналов ядра, открывается узел устройства / dev / kmsg, то его можно передать cat /dev/kmsg Чтобы получить журнал ядра.
Затем установите уровень вывода журнала на KLOG_NOTICE_LEVEL (5). Когда уровень журнала меньше 5, он будет выводиться в журнал ядра. Значение по умолчанию — 3.
1.3 console_init_action
Это экран с ANDROID внизу экрана загрузки.
1.4 restart_processes
Проверьте все службы в service_list. Для служб с флагом SVC_RESTARTING будет вызван соответствующий restart_service_if_needed.
Затем вызовите service_start, чтобы запустить службу.
Затем интерпретируйте четыре основные точки знаний в основном методе инициализации: обработка сигналов, синтаксис файла RC, службы запуска и службы атрибутов.
Два, обработка сигналов
В методе main () файла init.cpp в разделе [1.1] signal_handler_init () используется для инициализации процесса обработки сигнала.
- Инициализировать дескриптор сигнала;
- Циклическая обработка дочерних процессов;
- Зарегистрируйте дескриптор epoll;
- Обработать завершение дочернего процесса;
2.1 signal_handler_init
Каждый процесс должен сначала регистрироваться при обработке сигнальных сигналов, отправленных другими процессами. Когда рабочее состояние процесса изменяется или завершается, генерируется определенный сигнальный сигнал. Процесс init является родительским процессом для всех процессов пользовательского пространства, а когда его дочерний процесс процессы завершаются Когда генерируется сигнал SIGCHLD, процесс init вызывает функцию установки сигнала sigaction (), передает параметры в структуру sigaction и завершает процесс обработки сигнала.
Есть две важные функции: SIGCHLD_handler и handle_signal, а именно:
2.2 reap_any_outstanding_children
Дополнительно: через getprop | grep init.svc Вы можете просмотреть текущее состояние всех служб. Статус делится на: работает, остановлен, перезапуск.
2.3 register_epoll_handler
Когда fd доступен для чтения, он вызовет функцию call (* fn).
Три, синтаксис файла rc
Синтаксис файла rc — это конечная единица строки, синтаксис, разделенный пробелами, начиная с # для представления строк комментариев. Файл rc в основном содержит Action, Service, Command, Options, среди которых имена Action и Service уникальны, а повторяющиеся имена считаются недопустимыми.
3.1 Action
Действие: Определите время выполнения соответствующей службы с помощью триггера, т. Е. Оператора, начинающегося с on. Конкретные сроки следующие:
- on Early-init; Срабатывает на ранней стадии инициализации;
- on init; срабатывает на этапе инициализации;
- on late-init; срабатывает на поздней стадии инициализации;
- при загрузке / зарядном устройстве: срабатывает при запуске / зарядке системы и других ситуациях, которые здесь не перечислены;
- on property: =: запускать, когда значение свойства соответствует условию;
3.2 Service
Служба Служба, начиная с службы, запускается процессом init и обычно выполняется в дочернем процессе init, поэтому перед запуском службы необходимо определить, существует ли соответствующий исполняемый файл. Дочерние процессы, сгенерированные init, определены в файле rc, и каждая служба будет генерировать дочерние процессы с помощью fork при запуске.
Например: service servicemanager /system/bin/servicemanager Он представляет собой имя службы — servicemanager, а путь выполнения службы — / system / bin / servicemanager.
3.3 Command
Вот часто используемые команды
- class_start : запускать все службы, принадлежащие одному классу;
- start : запустить указанную службу, пропустить ее, если она уже запущена;
- stop : остановить работающую службу
- setprop: установить значение свойства
- mkdir
: Создать указанный каталог
: Записать строку в путь к файлу;
3.4 Options
Опции не являются обязательными для Сервиса, используются вместе с Сервисом
- отключено: не запускается автоматически с классом, запускается только в соответствии с именем службы;
- oneshot: служба не перезапускается после выхода;
- пользователь / группа: установите пользователя / группу пользователей, которые запускают службу, по умолчанию — root;
- class: Установите имя класса, к которому он принадлежит. Когда класс, к которому он принадлежит, запускается / завершается, служба также запускается / останавливается. Значение по умолчанию — default;
- onrestart: выполнить соответствующую команду при перезапуске службы;
- сокет: создан с именем /dev/socket/ Разъем
- критично: если служба будет постоянно перезапускаться в течение указанного времени, система перезагрузится и перейдет в режим восстановления.
default: Это означает disabled = false, oneshot = false, critical = false.
В-четвертых, запустите службу
4.1 Последовательность запуска
Последовательность выполнения триггера: Early-init -> init -> late-init. Из приведенного выше кода мы видим, что монтирование файловой системы и при загрузке запускаются в триггере late-init. Процесс загрузки запустит основной класс. Что касается запуска основного класса, то он определяется настройками следующих 4 значений vold.decrypt.Процесс находится в файле system / vold / cryptfs.c.
4.2 Запуск службы (Zygote)
В файле init.zygote.rc служба zygote определяется следующим образом:
от init_parser.cpp После завершения всей работы по анализу сервиса, процесс анализа здесь подробно обсуждаться не будет.Основными задачами процесса являются:
- Создайте служебную структуру под названием «зигота»;
- Создайте структуру socketinfo для связи через сокет;
- Создайте структуру действий, содержащую 4 перезапуска.
Сервис Zygote запустится с запуском основного класса. После выхода zygote будет перезапущен init. Даже если он будет перезапущен несколько раз, он не войдет в режим восстановления. Исполняемый файл, соответствующий zygote, — это / system / bin / app_process, путем вызова pid =fork() Создайте дочерний процесс через execve(svc->args[0], (char**)svc->args, (char**) ENV) , Войдите в функцию main () App_main.cpp. Итак, зигота создается с помощью fork и execv вместе.
Процесс выглядит следующим образом:
Что касается перезапуска Zygote, упомянутого в предыдущем процессе обработки сигналов, он предназначен для обработки сигнала SIGCHLD, а процесс init перезапускает процесс zygote. Для получения дополнительной информации о Zygote см.Зиготные статьи。
4.3 Перезапуск службы
Когда дочерний процесс init завершается, он генерирует сигнал SIGCHLD и отправляет его процессу init, передает данные через сокет сокета, вызывает метод wait_for_one_process () и решает, следует ли перезапустить дочерний процесс или отказаться от запуска в зависимости от того, это один выстрел.
Во всех сервисах есть только servicemanager, zygote и surfaceflinger. onrestart Ключевые слова для запуска процесса запуска других служб.
Это видно из вышеизложенного:
- zygote: инициировать перезапуск медиа, netd и дочерних процессов (включая процесс system_server);
- system_server: запустить перезапуск зиготы;
- Surfaceflinger: запустить зиготу для перезапуска;
- servicemanager: Trigger zygote, healthd, media, surfaceflinger, drm для перезапуска
Следовательно, завершение работы Surfaceflinger, servicemanager, самой зиготы и процесса system_server вызовет перезапуск Zygote.
Пять, атрибутная служба
Когда процесс A изменяет значение свойства с помощью property_set (), процесс инициализации проверяет права доступа. Когда разрешения соответствуют требованиям, соответствующее значение свойства будет изменено. После изменения значения свойства соответствующий триггер (т. Е. Rc file) будет запущен. Оператор в начале on), в Android Shared Memmory (общая область памяти) есть область _system_property_area_, в которой записываются все значения свойств. Для процесса A с помощью метода property_get () также получается значение свойства общей области памяти.
5.1 property_init
Основная функция этого метода — выполнение метода __system_property_area_init () для создания общей памяти для кросс-процессов. Основная работа такова:
- Выполните open (), откройте имя «/ dev /properties«Файл с общей памятью и установите размер 128 КБ;
- Выполните mmap (), чтобы отобразить память процессу инициализации;
- Первый адрес памяти сохраняется в глобальной переменной __system_property_area__, и последующие добавления или изменения свойств основываются на этой переменной для вычисления местоположения.
О загруженном проп-файле
от load_all_load_all_propsprops() Метод, загрузите следующее:
- /system/build.prop;
- /vendor/build.prop;
- /factory/factory.prop;
- /data/local.prop;
- Свойство persist по пути / data / property
5.2 start_property_service
Создайте и контролируйте сокет с именем «property_service», а затем используйте epoll_ctl, чтобы установить дескриптор файла свойств для запуска читаемой функции обратного вызова handle_property_set_fd, а затем посмотрите на реализацию этой функции.
5.3 handle_property_set_fd
Здесь 2-секундный тайм-аут установлен для события приема сокета, что означает, что процесс установки свойства может занять много времени.
5.4 handle_property_set
Здесь он проверит, соответствует ли имя атрибута. Конкретные спецификации проверки следующие:
Логика выполнения разных атрибутов разная, основные отличия заключаются в следующем:
Имя атрибута начинается с
Вначале это означает, что это управляющее сообщение, которое используется для выполнения некоторых команд. Например:
- setprop ctl.start bootanim просмотр анимации загрузки;
- setprop ctl.stop bootanim Отключить загрузочную анимацию;
- setprop ctl.start pre-recovey переходит в режим восстановления;
Имя атрибута начинается с ro. Вначале это означает, что он доступен только для чтения и не может быть установлен, поэтому он возвращается напрямую;
Имя атрибута начинается с persist. Вначале вам нужно записать эти значения в соответствующий файл; следует отметить, что persist используется для сохранения определенных значений атрибутов, но также приносит дополнительные операции ввода-вывода.
Шесть, резюме
Процесс init (pid = 1) — это первый процесс в пространстве пользователя в системе Linux, и его основные задачи следующие:
- Создайте общую память для сервера атрибутов;
- Проанализируйте каждый RC-файл и запустите соответствующий процесс службы атрибутов;
- Инициализируйте epoll, установите соответствующие функции обратного вызова signal, property и keychord, когда три fd доступны для чтения;
- Войдите в состояние бесконечного цикла и выполните следующий процесс:
- Проверить, пуст ли список action_queue, если он не пустой, выполнить соответствующее действие;
- Проверьте, нужно ли перезапускать процесс, и перезапустите его, если он есть;
- Войдите в состояние ожидания epoll_wait до тех пор, пока событие изменения системного свойства (свойство_set не изменит значение свойства), или сигнал SIGCHLD от дочернего процесса не будет получен, или событие ввода с клавиатуры keychord, он выйдет из состояния ожидания и выполнит соответствующую функцию обратного вызова.
Можно видеть, что основная работа процесса инициализации после загрузки заключается в том, чтобы реагировать на события изменения свойств и восстанавливать зомби-процесс. Когда процесс вызывает свойство_set для изменения значения системного свойства, система отправляет уведомление о событии изменения свойства процессу init через сокет, затем свойство fd станет доступным для чтения, а процесс init будет использовать механизм epoll для мониторинга fd. и вызвать метод обратного вызова handle_property_set_fd (). Повторное использование зомби-процессов в ядре Linux, если родительский процесс завершается, не дожидаясь окончания дочернего процесса, дочерний процесс после завершения станет зомби-процессом, занимая системные ресурсы. По этой причине процесс init специально устанавливается с приемником сигнала SIGCHLD. Когда некоторые дочерние процессы завершаются и обнаруживают, что их родительский процесс завершился, он отправляет сигнал SIGCHLD процессу init, и процесс init вызывает метод обратного вызова handle_signal (), чтобы вернуть дочерний процесс зомби.
Источник
Основы безопасности операционной системы Android. Native user space, ч.1
Вступление
В этой статье я попробую рассмотреть безопасность чуть-чуть повыше ядра, а именно: как работает безопасность в Native user space. Мы коснемся темы процесса загрузки операционной системы и рассмотрим структуру файловой системы Android. Как я уже говорил, я не очень силен в Linux, поэтому если заметите неточности, то исправляйте — меня научите и статью улучшите. Так как эта тема довольно обширная, я решил разбить её на две части. В первой части мы рассмотрим процесс загрузки операционной системы и особенности файловой системы. Всем кому интересно, добро пожаловать!
Список статей
Что подразумевается под Native user space
Под Native user space подразумеваются все компоненты пространства пользователя, которые выполняются вне Dalvik Virtual Machine, и которые не являются частью Linux kernel.
Файловая система Android
Для начала давайте рассмотрим структуру файловой системы Android. Хотя Android и базируется на Linux kernel, привычную нашему глазу структуру файловой системы мы здесь не увидим. Давайте запустим эмулятор и посмотрим, что у нас есть. Для этого выполним комманду:
В моем терминале для эмулятора на Android 4.2 я вижу следующий результат:
Я отмечу здесь только главные директории и те, которые нам пригодятся в будущем. В Интернете можно найти описание и предназаначение других директорий. Можно заметить, что некоторые директории такие же, как и в Linux, например, /dev, /proc, /sys, /mnt, /etc И их предназначение в основном такое же, как и в Linux. Кстати, отметьте, что мы не видим /bin и /lib директорий. Где они скрылись, я расскажу чуть позже.
C другой стороны можно заметить директории, которых в Linux вообще нет. Среди них нас интересуют /data, /system, /cache, /init, /init.rc Давайте рассмотрим их назначение поподробнее.
/system Это главная директория, где хранятся неизменяемые компоненты Android системы. Если проводить аналогию, то эта папка похожа на папку C:\windows\, доступную только для чтения. Т.е. изменять данные в этой директории мы не можем. Как раз здесь можно найти директории /bin и /lib, где хранятся различные исполняемые файлы и shared libraries. Кроме того, здесь же лежат системные приложения, которые встроены в операционку и которые, по умолчанию, нельзя удалить. Содержимое этой директории формируется во время компиляции операционной системы.
/data Т.к. /system у нас доступна только для чтения, то должна быть директория где хранятся изменяемые данные. /data как раз ею и является. Например, в эту директорию в /data/app сохраняются apk файлы устанавливаемых приложений, а в /data/data хранятся их данные (эту директорию мы подробно рассматривали в прошлой статье).
/cache Это просто временное хранилище. Также в эту директорию сохраняются, а потом из неё запускаются системные обновления.
Чтобы понять, что такое /init файл и для чего нужны непонятные файлы с расширением *.rc, рассмотрим процесс загрузки системы.
Процесс загрузки Android
Давайте рассмотрим несколько шагов процесса загрузки операционной системы Android. Эта картинка взята из книги «Embedded Android», там же можно найти и более детальное описание. Хотя в целом я и понимаю процесс, но для меня это больше магия 🙂
CPU. Когда вы нажимаете на кнопку включения, на процессор вашего устройства начинает подаваться напряжение. Так как до этого момента процессор был выключен, и так как он не способен сохранять свое состояние без подачи напряжения, то сразу после старта он находится в некотором неинициализированном состоянии. В данном случае процессор считывает из своего специального регистра некоторый жестко зашитый адрес и начинает выполнять инструкции начиная с него. Чаще всего, этот адрес указывает на чип, в который зашит bootloader (загрузчик).
Bootloader. Bootloader инициализирует RAM и загружает в неё Linux kernel. Кроме того Bootloader создает RAMdisk.
Linux kernel. Ядро инициализирует различные подсистемы, встроенные драйвера и монтирует root filesystem (корневую файловую систему). После этого ядро может запускать первую программу.
На этом магия заканчивается и дальше всё становится более-менее понятно.
Первой программой в случае Android является init. Исполняемый файл находится в корневой директории (/init). Именно эту программу стартует ядро после своей загрузки. Её исходники находятся в папке system/core/init/ Давайте в них слегка покопаемся. Нас интересует system/core/init/init.c:
Вначале мы создаем и монтируем некоторые необходимые для работы директории, а потом парсим файл /init.rc и выполняем то, что распарсили. Формат /init.rc файла очень хорошо описан в readme, там же можно найти и пример. Если кратко, то этот файл представляет собой набор actions (секций — именнованная последовательность комманд). Каждая последовательность команд срабатывает по определенному trigger (триггеру). Например, следующая последовательно — это action, в которой trigger — это fs, а последовательность команд — это набор mount команд:
Исходный файл /init.rc находится в system/core/rootdir/init.rc Давайте рассмотрим некоторые основные его части, хотя я вам очень советую просмотреть его полность. После этого многие вещи вам должны стать понятны. Итак, начинается наш файл следующими строками:
Они означают, что кроме init.rc файла нужно также импортировать настройки из файлов init.usb.rc, init.trace.rc и из файла с непонятным именем init.$
После этого происходит инициализация переменных, необходимых для работы устройства. Если вас заинтересует эта тема, то вы легко найдете информацию о той или иной комманде. Давайте подробно рассмотрим следующий блок (который я уже приводил в этой статье):
MTD — Memory Technology Devices. Если в общих чертах, то MTD — это специальный чип с энергонезависимой (т.е. данные на этом чипе сохраняются после перезагрузки или выключения) flash-памятью (типа NOR или NAND), на который сохраняются образы дисков. В этой статье более подробно рассказывается об этом типе устройств, а также об ограничениях. Специально для этих разновидностей flash-памяти были разработаны специальные файловые системы, например, YAFFS. Одно из самых важных ограничений этих типов памяти заключается в том, что для того чтобы записать данные в сектор, куда уже записаны какие-то данные, вам надо полностью сначала стереть весь сектор. Поэтому производители стали переходить на новый тип блочной flash-памяти (eMMC), на которые можно поставить обычную ext4 файловую систему и избавиться от указанного ограничения. Т.к. я показываю пример init.rc файла для эмулятора, где вся работа эмулируется, то в нем по умолчанию используется файловая система YAFFS2 (думаю, что это пережитки прошлого, т.к. YAFFS2 использовалась для всех устройств до Android 2.2). В реальном устройстве (это как раз один из примеров, когда необходимо использовать init.rc файл для определенного железа) эти комманды будут перезаписаны. Например, в случае устройства herring (Google Nexus S), в файле init.herring.rc эта секция выглядит следующим образом:
Где fstab.herring — это файл, содержимое которого выглядит следующим образом:
Как вы могли заметить, /system, /data, /cache — это просто mounting points (точки монтирования файловой системы), которые указывают либо на MTD устройства (в случае эмулятора), либо на блочные устройства (в случае настоящего устройства), куда записаны соответствующие дисковые образы (system.img, userdata.img и cache.img). Я не уверен, но думаю, что внутри смартфона находится один единственный чип с flash-памятью, разделенный на partitions (тома), в каждый из которых записан соответствующий образ. Этот чип с flash-памятью — то, что мы знаем под именем Internal storage (внутренняя память), объем которой — один из основных параметров смартфона.
Следует заметить, что /system смонтирован read-only (только для чтения). Это означает, что содержимое данного раздела не изменяется в процессе работы устройства, а только когда вы, например, обновляете систему на вашем устройстве (используя системные обновления).
Продолжим рассматривать наш init.rc. По триггеру post-fs-data формируется базовая структура файловой системы /data раздела. Там, в общем всё понятно — набор mkdir, chown, chmod команд.
Далее init.rc запускает несколько демонов. Если вернуться к рисунку в начале статьи, то они перечислены в блоке Native daemons. На этом мы пока остановимся. Как вы могли заметить из рисунка, я не полностью рассмотрел процесс загрузки операционной системы. Некоторые непокрытые этапы я рассмотрю в следующих статья.
Заключение
В следующей части я расскажу, откуда берутся образы system.img, userdata.img и cache.img и рассмотрю безопасность на уровне Native user space. Как всегда приветствуются исправления, дополнения, а так же предложения, о чем написать. И хотя у меня уже есть некоторый план, о чем писать в следующих статья, я готов его подкорректировать.
Ссылки
Update
- Комментарий от пользователя bmx666 про различные варианты размещения загузчика на MTD устройствах.
- Комментарий от пользователя SamOwaR про инициализацию CPU на разных SoC
Источник