- Стандартная система инициализации (init.d и др.)
- Основы безопасности операционной системы Android. Native user space, ч.1
- Вступление
- Список статей
- Что подразумевается под Native user space
- Файловая система Android
- Процесс загрузки Android
- Заключение
- Ссылки
- Русские Блоги
- Подробный процесс инициализации Android (1)
Стандартная система инициализации (init.d и др.)
А у Android вообще есть какой-то стандартный автостарт, куда можно положить свой скрипт? Init.d не везде поддерживается, вроде как (можно самому добавить вроде).
У себя я обнаружил скрипты вида /system/etc/init.*.sh , это тоже не стандарт и не везде встречается?
Самому и надо добавить, пересобрав boot.img
Ну а что там, общего стандарта нет? Чем-то же там запускается всё.
покажите этот ваш стандарт
Так я и спрашиваю, нет ли какого-то стандарта в этих ваших андроидах.
У себя я обнаружил скрипты вида /system/etc/init.*.sh
Кстати, мой скрипт, аналогично расположенный по такому пути (типа /system/etc/init.myscript.sh ) не заработал.
Таки пришлось init.d запиливать у себя.
По другому организовано это.
Так это для полноценных приложений (по ссылке про java). А служебные фоновые процессы (скрипты или нативные) же как-то запускаются.
стандартный скрипт называется init.rc лежит собственно в корне фс, зачитывает его процесс init, хотя конечно отдельным вендорам не запрещено вкрутить туда чтото свое вместо этой системы инициализации, то как править вышеописанный скрипт чтоб он запускал все что вам угодно надо гуглить, в сети море информации
стандартный скрипт называется init.rc лежит собственно в корне фс, зачитывает его процесс init,
Хм, действительно, есть там, спасибо! А я там даже не искал, в /etc смотрел только.
то как править вышеописанный скрипт чтоб он запускал все что вам угодно надо гуглить, в сети море информации
Перемонтировать с rw и всё.
Он же лежит в initramfs, т.е. распаковывается при загрузке из образа. Твои правки потеряются, если ты не перешьешь bootimage.
Если делать правильно, то нужно писать сервис. Минимум кода на java, для контроля прав и регистрации в системе придется добавить. Остальное может быть кодом на Си++ и скриптом.
Действительно, mount показывает rootfs / rootfs ro,relatime 0 0 . Это с /system так прокатывало…
Источник
Основы безопасности операционной системы 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
Источник
Русские Блоги
Подробный процесс инициализации Android (1)
14 апреля 2013 г. 20:06:42 geekguy Просмотров 7785Больше
Колонка: Android Deep Discovery
Заявление об авторском праве: эта статья является оригинальной статьей блоггера и не может быть воспроизведена без разрешения блоггера.https://blog.csdn.net/nokiaguy/article/details/8800962
Процесс инициализации Android (два); анализ языка инициализации (init.rc)
Версия программного обеспечения, использованная в этой статье
Ядро Linux: 3.1.10
В этой и последующих статьях будет подробно проанализирован процесс инициализации Android, детально проанализирован и рассмотрен большой объем знаний в надежде помочь читателям понять процесс запуска Android. Эта глава в основном знакомит с определением имен файлов инициализации, связанных с оборудованием, а также с принципом и реализацией сервисов атрибутов.
Android — это операционная система, основанная на ядре Linux. Аналогичен Ubuntu Linux и Fedora Linux. Просто в Android добавлена уникальная поддержка мобильных устройств на уровне приложений. Поскольку Android — это система ядра Linux, основной процесс запуска должен также соответствовать правилам Linux. Если вы изучали другие системы Linux, вы должны понимать, что полная система Linux сначала загружает ядро Linux в память, то есть файл bzImage, сгенерированный путем компиляции исходного кода ядра Linux, и файл zImage для исходного кода ядра Linux, оптимизированный для Android. Этот файл является двоичной версией ядра Linux. Поскольку zImage работает в пространстве ядра, а программное обеспечение, которое мы обычно используем, работает в пространстве приложения (для подробного описания пространства ядра и пространства приложения вы можете обратиться к книге «Android Deep Discovery (Vol. 1): HAL и разработка драйверов»). В последующих томах будет проведен комплексный анализ всей системы Android). Пространство ядра и пространство приложения не могут быть доступны напрямую через уровень адресации памяти, поэтому необходимо установить какой-то механизм связи.
В настоящее время в Linux имеется множество механизмов связи, которые могут взаимодействовать между пространством пользователя и пространством ядра, например, файлы драйверов устройств (находятся в каталоге / dev) и файлы памяти (каталог / proc, / sys и т. Д.). Студенты, знающие Linux, должны знать, что одной из важных характеристик Linux является то, что все существует в форме файлов, например, устройство обычно соответствует одному или нескольким файлам устройства. Эти файлы, которые взаимодействуют с пространством ядра, находятся в пользовательском пространстве, поэтому после загрузки ядра Linux необходимо сначала создать каталог, в котором расположены эти файлы. Программа, которая выполняет эти задачи, является инициалом, который представит эта статья. Init — это программа командной строки. Одна из его основных задач — создать каталог, в котором находятся эти файлы, взаимодействующие с пространством ядра. Когда ядро Linux загружено, первое, что нужно сделать, это вызвать программу init, то есть init — это первая программа, выполняемая в пространстве пользователя.
Прежде чем анализировать основной код init, необходимо предварительно понять, что помимо создания некоторых каталогов он также выполняет следующую работу
Хотя init мало что делает, код очень сложный. Программа Init не состоит из файла исходного кода, но связана с набором объектных файлов файла исходного кода. Эти файлы расположены в следующих каталогах.
/ system / core / init
Где init.c — основной файл init. Теперь откройте файл и посмотрите его содержимое. Поскольку init — это программа командной строки, анализ init.c должен начинаться с главной функции. Теперь она лучше основной функции. Код выглядит следующим образом:
Мы можем видеть, что основная функция очень сложна, но нам не нужно делать каждое утверждение очень четким (потому что это очень сложно сделать), обычно нужно понимать только основную строку init. На самом деле, это видно из основной функции init. Init фактически разделен на следующие две части.
Первая работа хорошо понятна. Вторая задача — ядро init. В системе Linux init — это родительский процесс всех процессов в пространстве приложения. Поэтому мы обычно выполняем команды в терминале Linux и создаем процессы. Это на самом деле сделано в этом бесконечном цикле. Другими словами, после выполнения команды ps -e в терминале Linux все процессы, кроме init, рассматриваются как созданные init. И init будет резидентом. Конечно, если init зависает, система Linux в основном падает.
Поскольку init более сложен, эта статья анализирует только его часть, а основные компоненты init будут подробно проанализированы в последующих статьях.
Основная задача создания каталога в начале основной функции относительно проста, и в этой части анализировать нечего. Это вызов какого-то общего API (mkdir) для создания некоторых каталогов. Теперь скажем несколько отступлений, поскольку исходный код Android (включая init) на самом деле относится к области прикладного программирования Linux, поэтому для полного понимания исходного кода Android, в дополнение к пониманию базовой структуры Linux, API уровня приложений Linux должен быть знаком , Чтобы удовлетворить потребности этих читателей, в будущем я напишу несколько статей о разработке приложений для Linux. Хорошо, теперь, когда мы вернулись к работе, давайте проанализируем более важную часть: анализ файла конфигурации.
Файл конфигурации здесь в основном относится к init.rc. Читатель может войти в оболочку Android и увидеть, что в корневом каталоге есть файл init.rc. Этот файл доступен только для чтения, даже если у вас есть права доступа root, вы можете изменить файл. Поскольку файлы, которые мы видим в корневом каталоге, являются просто изображениями файлов памяти. Другими словами, после запуска Android он загружает файл init.rc в память. Изменение содержимого файла init.rc на самом деле просто изменение содержимого файла init.rc в памяти. После перезапуска Android содержимое файла init.rc будет восстановлено до первоначальной загрузки. Единственный способ полностью изменить содержимое файла init.rc — это изменить образ ядра (boot.img) в ПЗУ Android. Фактически, boot.img называется образом ядра, но помимо полного файла ядра Linux (zImage), он также содержит другой файл образа (ramdisk.img). ramdisk.img содержит файл init.rc и команду init. Таким образом, файл init.rc может быть полностью изменен только путем изменения файла init.rc в файле ramdisk.img, перепаковки файла boot.img и перепрошивки компьютера. Если у читателя есть исходный код Android, после компиляции вы увидите, что соответствующие подкаталоги в каталоге out сгенерируют корневой каталог, который фактически является содержимым ramdisk.img после распаковки. Вы увидите команду init и файл init.rc. Как изменить файл init.rc и как прошить аппарат, будет обсуждаться в следующих статьях. Тем не менее, это содержание не имеет отношения к этой статье, поэтому они не будут обсуждаться подробно.
Теперь вернемся к основной функции. После создания каталога вы увидите, что следующие 3 функции выполняются.
Среди них, property_init в основном выделяет некоторое пространство для хранения свойств, эта функция не является основной. Однако, когда мы смотрим на файл init.rc, мы обнаруживаем, что в начале файла используются некоторые операторы import для импорта других файлов конфигурации, например, /init.usb.rc. Большинство файлов конфигурации используют определенное имя файла напрямую. Только следующий код использует переменную ($
Первое, что нужно понять, это то, что содержимое файла конфигурации init. $
Из кода метода get_hardware_name можно узнать, что этот метод в основном используется для определения значений переменных оборудования и версии. Редакция здесь не обсуждается, пока мы изучаем оборудование. Источником оборудования является командная строка ядра Linux или содержимое файла / proc / cpuinfo. Командная строка ядра Linux пока не обсуждается (поскольку это значение редко передается). Сначала посмотрите на / proc / cpuinfo. Этот файл является виртуальным файлом (файлом памяти). Если вы выполните команду cat / proc / cpuinfo, вы увидите содержимое этого файла. Как показано на рисунке 1. В белом поле находится значение поля Hardware. Поскольку устройство является Nexus 7, значение является группером. Если программа здесь, имя файла конфигурации, связанного с оборудованием, — init.grouper.rc. Читатели с Nexus 7 увидят, что в корневом каталоге действительно есть файл init.grouper.rc. Обратите внимание, что собственное ПЗУ Nexus 7 не задает имя файла конфигурации в другом месте, поэтому имя файла конфигурации — это значение, взятое из поля «Оборудование» файла / proc / cpuinfo.
Теперь посмотрите на функцию process_kernel_cmdline, вызываемую после функции get_hardware_name, код выглядит следующим образом:
Помимо использования функции import_kernel_cmdline для импорта переменных ядра в функции process_kernel_cmdline, основной функцией является вызов функции export_kernel_boot_props для установки переменных ядра через свойства, например, для установки аппаратных переменных через свойство ro.boot.hardware, что означает, что свойство ro.boot.hardware Это значение может изменить значение аппаратного поля, полученного из файла / proc / cpuinfo в функции get_hardware_name. Давайте посмотрим на код функции export_kernel_boot_props.
Как видно из кода функции export_kernel_boot_props, эта функция фактически устанавливает некоторые значения свойств вперед и назад и использует некоторые значения свойств для изменения переменных, таких как консоль и оборудование. Аппаратная переменная (то есть массив из 32 символов) была получена один раз из файла / proc / cpuinfo в функции get_hardware_name, а значение устанавливается один раз через свойство ro.boot.hardware в функции export_kernel_boot_props, но в Этот атрибут не установлен в Nexus 7, поэтому значение аппаратного обеспечения все еще является групповым. Наконец, свойство ro.hardware устанавливается с помощью аппаратной переменной, поэтому конечный файл инициализации называется init.grouper.rc.
Вот еще один вопрос. Я уже упоминал о свойствах или файлах свойств много раз. Так что же означают эти файлы свойств? Такое init.rc? Конечно нет. Фактически, эти файлы свойств являются файлами конфигурации, которые расположены в разных каталогах и последовательно считываются системой.
Вы должны понять, как init обрабатывает эти атрибуты, прежде чем изучать эти файлы конфигурации. Читатели, написавшие собственные приложения для Windows, должны понимать, что в Windows есть механизм реестра, который предоставляет большое количество атрибутов в реестре. В Linux есть похожий механизм, это служба атрибутов. Init запустит службу свойств (сервис Socket) во время процесса запуска и установит область памяти в памяти для хранения этих свойств. При чтении этих свойств читайте непосредственно из этой области памяти. Если вы изменяете значение свойства, вам необходимо заполнить его через службу свойств подключения Socket. В функции действия в файле init.c вызывается функция start_property_service для запуска службы свойств. Действие — это механизм выполнения в init.rc и аналогичных файлах. Поскольку имеется много содержимого, выполнение в файле init.rc Механизм будет подробно обсуждаться в следующей статье.
Теперь вы можете найти функцию start_property_service в файле Property_service.c, который находится в том же каталоге, что и файл init.c.
Теперь, когда мы знаем, как запустить службу свойств, следующие два макроса также задействованы в функции start_property_service.
Оба этих макроса являются путями к системным именам файлов свойств. Чтобы получить определение этих макросов, мы сначала проанализируем другую функцию.
В предыдущем чтении значения свойства использовалась функция property_get, которая реализована в Property_service.c. Код выглядит следующим образом:
Видно, что базовая функция __system_property_find вызывается в функции property_get, и эта функция действительно реализует функцию получения значения свойства. Эта функция принадлежит библиотеке bionic и реализована в файле system_properties.c. Читатель может найти файл в следующем каталоге.
/ bionic / libc / bionic
Код функции __system_property_find выглядит следующим образом:
Из кода функции __system_property_find легко увидеть, что в первой строке используется переменная __system_property_area__, которая является глобальной. В предыдущем анализе основной функции была задействована функция property_init, которая называлась функцией init_property_area, которая используется для инициализации области памяти свойств, то есть переменной __system_property_area__.
В заголовочном файле system_properties.h, соответствующем файлу system_properties.c, упомянутому ранее, определены два вышеупомянутых макроса, представляющих путь к файлу свойств.На самом деле, есть два других макроса, представляющих путь. Всего имеется четыре файла свойств. Файл system_properties.h находится в / bionic / libc / include / sys. Четыре макроса определены следующим образом:
Теперь читатели могут войти в соответствующий каталог устройства Android, обычно вы можете найти вышеуказанные файлы 4. Как правило, вы найдете файл default.prop в корневом каталоге, а cat default.prop увидит содержимое файла. Служба свойств загружает все свойства во все четыре файла свойств и свойства, установленные с помощью property_set. На терминале устройства Android вы можете напрямую использовать команду getprop, чтобы получить все значения свойств из службы свойств. Как показано на рисунке 2. Команда getprop также может напрямую получить конкретное значение свойства на основе имени свойства, например, getprop ro.build.product.
Если читатель заинтересован, вы можете увидеть, как getprop читает и записывает свойства через службу свойств. Файл исходного кода для команды getprop — getprop.c. Читатель может найти файл в / system / core / toolbox. Фактически, получение значений свойств с помощью getprop также выполняется с помощью функции property_get. Эта функция была проанализирована ранее, и фактически была вызвана функция __system_property_find для получения соответствующего значения свойства из области памяти, указанной в переменной __system_property_area__.
Кроме того, в файле system_properties.c есть две следующие функции для изменения или добавления значения свойства через службу свойств.
Переменная property_service_socket участвует в функции send_prop_msg, которая определяется следующим образом:
Источник