---
url: https://kernelsu.org/ru_RU/guide/module.md
---
# Руководство по разработке модулей {#introduction}

KernelSU предоставляет механизм модулей, позволяющий добиться эффекта модификации системного каталога при сохранении целостности системного раздела. Этот механизм принято называть "бессистемным".

Модульный механизм KernelSU практически аналогичен механизму Magisk. Если вы знакомы с разработкой модулей Magisk, то разработка модулей KernelSU очень похожа. Представление модулей ниже можно пропустить, достаточно прочитать \[различия-с-magisk] (difference-with-magisk.md).

::: warning МЕТАМОДУЛЬ ТРЕБУЕТСЯ ТОЛЬКО ДЛЯ МОДИФИКАЦИИ СИСТЕМНЫХ ФАЙЛОВ
KernelSU использует архитектуру [метамодулей](metamodule.md) для монтирования директории `system`. **Только если вашему модулю нужно модифицировать файлы `/system`** (через директорию `system`), вам необходимо установить метамодуль (например, [meta-overlayfs](https://github.com/tiann/KernelSU/releases)). Другие функции модулей, такие как скрипты, правила sepolicy и system.prop, работают без метамодуля.
:::

## WebUI

KernelSU modules support displaying interfaces and interacting with users. See the [WebUI documentation](module-webui.md) for additional details.

## Конфигурация модулей

KernelSU предоставляет встроенную систему конфигурации, которая позволяет модулям хранить постоянные или временные настройки в формате ключ-значение. Подробности смотрите в [документации по конфигурации модулей](module-config.md).

## Одноразовые скрипты

ZIP-архив модуля также может быть одноразовым скриптом, который менеджер KernelSU запускает один раз вместо установки. Подробности смотрите в [документации по одноразовым скриптам](module-script.md).

## Busybox

В комплект поставки KernelSU входит полнофункциональный бинарный файл BusyBox (включая полную поддержку SELinux). Исполняемый файл находится по адресу `/data/adb/ksu/bin/busybox`. BusyBox от KernelSU поддерживает переключаемый во время работы "ASH Standalone Shell Mode". Этот автономный режим означает, что при запуске в оболочке `ash` BusyBox каждая команда будет напрямую использовать апплет внутри BusyBox, независимо от того, что задано в качестве `PATH`. Например, такие команды, как `ls`, `rm`, `chmod` будут **НЕ** использовать то, что находится в `PATH` (в случае Android по умолчанию это будут `/system/bin/ls`, `/system/bin/rm` и `/system/bin/chmod` соответственно), а вместо этого будут напрямую вызывать внутренние апплеты BusyBox. Это гарантирует, что скрипты всегда будут выполняться в предсказуемом окружении и всегда будут иметь полный набор команд, независимо от того, на какой версии Android они выполняются. Чтобы заставить команду *не* использовать BusyBox, необходимо вызвать исполняемый файл с полными путями.

Каждый сценарий оболочки, запущенный в контексте KernelSU, будет выполняться в оболочке BusyBox `ash` с включенным автономным режимом. Для сторонних разработчиков это касается всех загрузочных скриптов и скриптов установки модулей.

Для тех, кто хочет использовать эту возможность "Автономного режима" вне KernelSU, есть два способа включить ее:

1. Установите переменной окружения `ASH_STANDALONE` значение `1`Пример: `ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh <script>`
2. Переключитесь с помощью параметров командной строки:`/data/adb/ksu/bin/busybox sh -o standalone <script>`

Чтобы убедиться, что все последующие запуски оболочки `sh` также выполняются в автономном режиме, предпочтительным методом является вариант 1 (и это то, что KernelSU и менеджер KernelSU используют внутри), поскольку переменные окружения наследуются вплоть до дочерних процессов.

::: tip отличие от Magisk

BusyBox в KernelSU теперь использует бинарный файл, скомпилированный непосредственно из проекта Magisk. \*\*Поэтому вам не нужно беспокоиться о проблемах совместимости между скриптами BusyBox в Magisk и KernelSU, поскольку они абсолютно одинаковы!
:::

## Модули KernelSU {#kernelsu-modules}

Модуль KernelSU - это папка, размещенная в каталоге `/data/adb/modules` и имеющая следующую структуру:

```txt
/data/adb/modules
├── .
├── .
|
├── $MODID                  <--- Папка имеет имя с идентификатором модуля
│   │
│   │      *** Идентификация модуля ***
│   │
│   ├── module.prop         <--- В этом файле хранятся метаданные модуля
│   │
│   │      *** Основное содержимое ***
│   │
│   ├── system              <--- Эта папка будет смонтирована, если skip_mount не существует
│   │   ├── ...
│   │   ├── ...
│   │   └── ...
│   │
│   │      *** Флаги состояния ***
│   │
│   ├── skip_mount          <--- Если он существует, то KernelSU НЕ будет монтировать вашу системную папку
│   ├── disable             <--- Если модуль существует, то он будет отключен
│   ├── remove              <--- Если модуль существует, то при следующей перезагрузке он будет удален
│   │
│   │      *** Необязательные файлы ***
│   │
│   ├── post-fs-data.sh     <--- Этот скрипт будет выполняться в post-fs-data
│   ├── service.sh          <--- Этот скрипт будет выполняться в сервисе late_start
|   ├── uninstall.sh        <--- Этот скрипт будет выполнен, когда KernelSU удалит ваш модуль
│   ├── system.prop         <--- Свойства из этого файла будут загружены в качестве системных свойств программой resetprop
│   ├── sepolicy.rule       <--- Дополнительные пользовательские правила sepolicy
│   ├── initrc/             <--- Файлы .rc в этом каталоге будут добавлены в init.rc при загрузке
│   │   ├── myservice.rc
│   │   └── ...
│   │
│   │      *** Автоматически генерируется, НЕЛЬЗЯ создавать или изменять вручную ***
│   │
│   ├── vendor              <--- Символьная ссылка на $MODID/system/vendor
│   ├── product             <--- Символьная ссылка на $MODID/system/product
│   ├── system_ext          <--- Симлинк на $MODID/system/system_ext
│   │
│   │      *** Допускается использование любых дополнительных файлов/папок ***
│   │
│   ├── ...
│   └── ...
|
├── another_module
│   ├── .
│   └── .
├── .
├── .
```

::: tip различия с Magisk
KernelSU не имеет встроенной поддержки Zygisk, поэтому в модуле нет содержимого, связанного с Zygisk. Однако для поддержки модулей Zygisk можно использовать [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext). В этом случае содержимое модуля Zygisk идентично содержимому, поддерживаемому Magisk.
:::

### module.prop

module.prop - это конфигурационный файл модуля. В KernelSU, если модуль не содержит этого файла, он не будет распознан как модуль. Формат этого файла следующий:

```txt
id=<string>
name=<string>
version=<string>
versionCode=<int>
author=<string>
description=<string>
updateJson=<url> (optional)
actionIcon=<path> (optional)
webuiIcon=<path> (optional)
```

* `id` должно соответствовать данному регулярному выражению: `^[a-zA-Z][a-zA-Z0-9._-]+$`
  экс: ✓ `a_module`, ✓ `a.module`, ✓ `module-101`, ✗ `a module`, ✗ `1_module`, ✗ `-a-module`
  Это **уникальный идентификатор** вашего модуля. Не следует изменять его после публикации.
* `versionCode` должен быть **целым**. Это используется для сравнения версий.
* Другими, не упомянутыми выше, могут быть любые **однострочные** строки.
* Обязательно используйте тип перевода строки `UNIX (LF)`, а не `Windows (CR+LF)` или `Macintosh (CR)`.
* `actionIcon` и `webuiIcon` — необязательные пути к изображениям, которые
  используются как значки по умолчанию для ярлыков действия и WebUI модуля в
  менеджере. Эти пути должны быть относительными к корневому каталогу модуля. Например,
  `actionIcon=icon/icon.png` будет интерпретирован как `<MODDIR>/icon/icon.png`.

::: tip ДИНАМИЧЕСКОЕ ОПИСАНИЕ
Поле `description` может быть динамически переопределено во время выполнения с помощью системы конфигурации модулей. Подробности см. в разделе [Переопределение описания модуля](module-config.md#overriding-module-description).
:::

### Сценарии командной оболочки {#shell-scripts}

Чтобы понять разницу между `post-fs-data.sh` и `Service.sh`, прочитайте раздел [Boot Scripts](#boot-scripts). Для большинства разработчиков модулей `service.sh` должно быть достаточно, если вам нужно просто запустить загрузочный скрипт.

Во всех скриптах вашего модуля используйте `MODDIR=${0%/*}` для получения пути к базовому каталогу вашего модуля; **НЕ** кодируйте жестко путь к вашему модулю в скриптах.

::: tip различия с Magisk
С помощью переменной окружения KSU можно определить, выполняется ли сценарий в KernelSU или в Magisk. Если скрипт выполняется в KernelSU, то это значение будет равно true.
:::

### каталог `system` {#system-directories}

После загрузки системы содержимое этого каталога будет наложено поверх раздела /system. Это означает, что:

::: tip ТРЕБОВАНИЕ МЕТАМОДУЛЯ
Директория `system` монтируется только если у вас установлен метамодуль, предоставляющий функциональность монтирования (например, `meta-overlayfs`). Метамодуль обрабатывает способ монтирования модулей. См. [Руководство по метамодулям](metamodule.md) для получения дополнительной информации.
:::

1. Файлы с теми же именами, что и в соответствующем каталоге в системе, будут перезаписаны файлами в этом каталоге.
2. Папки с теми же именами, что и в соответствующем каталоге в системе, будут объединены с папками в этом каталоге.

Если вы хотите удалить файл или папку в исходном каталоге системы, необходимо создать файл с тем же именем, что и файл/папка, в каталоге модуля с помощью команды `mknod filename c 0 0`. Таким образом, система overlayfs автоматически "забелит" этот файл, как если бы он был удален (раздел /system при этом фактически не изменится).

Вы также можете объявить в `customize.sh` переменную с именем `REMOVE`, содержащую список каталогов для выполнения операций удаления, и KernelSU автоматически выполнит команду `mknod <TARGET> c 0 0` в соответствующих каталогах модуля. Например:

```sh
REMOVE="
/system/app/YouTube
/system/app/Bloatware
"
```

В приведенном выше списке будут выполнены команды `mknod $MODPATH/system/app/YouTuBe c 0 0` и `mknod $MODPATH/system/app/Bloatware c 0 0`; при этом `/system/app/YouTube` и `/system/app/Bloatware` будут удалены после вступления модуля в силу.

Если вы хотите заменить каталог в системе, то необходимо создать каталог с тем же путем в каталоге модуля, а затем установить для этого каталога атрибут `setfattr -n trusted.overlay.opaque -v y <TARGET>`. Таким образом, система overlayfs автоматически заменит соответствующий каталог в системе (без изменения раздела /system).

Вы можете объявить в файле `customize.sh` переменную с именем `REPLACE`, содержащую список заменяемых каталогов, и KernelSU автоматически выполнит соответствующие операции в каталоге вашего модуля. Например:

REPLACE="
/system/app/YouTube
/system/app/Bloatware
"

В этом списке будут автоматически созданы каталоги `$MODPATH/system/app/YouTube` и `$MODPATH/system/app/Bloatware`, а затем выполнены команды `setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/YouTube` и `setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/Bloatware`. После вступления модуля в силу каталоги `/system/app/YouTube` и `/system/app/Bloatware` будут заменены на пустые.

::: tip различия с Magisk

KernelSU использует архитектуру [метамодулей](metamodule.md), где монтирование делегируется подключаемым метамодулям. Официальный метамодуль `meta-overlayfs` использует OverlayFS ядра для бессистемных модификаций, в то время как Magisk использует magic mount (bind mount), встроенный непосредственно в его ядро. Оба достигают одной цели: модификация файлов `/system` без физического изменения раздела `/system`. Подход KernelSU обеспечивает большую гибкость и уменьшает поверхность обнаружения.
:::

Если вы заинтересованы в использовании overlayfs, рекомендуется прочитать [документацию по overlayfs](https://docs.kernel.org/filesystems/overlayfs.html) ядра Linux.

### system.prop

Этот файл имеет тот же формат, что и `build.prop`. Каждая строка состоит из `[key]=[value]`.

### sepolicy.rule

Если для вашего модуля требуются дополнительные патчи sepolicy, добавьте эти правила в данный файл. Каждая строка в этом файле будет рассматриваться как утверждение политики.

### Инъекция initrc {#initrc-injection}

KernelSU предоставляет механизм для внедрения кастомных директив Android Init RC в системный `init.rc`. Это позволяет модулям регистрировать кастомные службы Android, устанавливать триггеры свойств или выполнять другие действия на языке Init без изменения системного раздела.

Во время загрузки модуль ядра KernelSU перехватывает системные вызовы `read()` и `fstat()`. Когда процесс init Android читает `/system/etc/init/hw/init.rc`, KernelSU прозрачно добавляет кастомное содержимое RC в конец файла. Процесс init анализирует эти внедренные директивы точно так же, как исходное содержимое init.rc.

На стороне пользовательского пространства ksud объединяет все файлы `.rc` из включенных модулей в один файл `modules.rc`, хранящийся в разделе `/metadata`. Этот файл автоматически пересоздается всякий раз, когда изменяется состояние модуля (установка, включение, отключение, удаление и т.д.).

#### Файлы initrc модуля

Создайте подкаталог `initrc/` в каталоге вашего модуля и поместите туда файлы `.rc`:

```txt
/data/adb/modules/<MODID>/
├── initrc/
│   ├── myservice.rc
│   └── another.rc
└── ...
```

::: tip

* Файлы должны иметь расширение `.rc`.
* Пока модуль включен, все файлы `.rc` в каталоге `initrc/` будут включены (разрешение на выполнение не требуется).
* Файлы обрабатываются в **алфавитном порядке имен файлов** внутри каталога, а модули обрабатываются в **алфавитном порядке ID модулей**.
  :::

#### Общие файлы initrc

Помимо файлов RC на уровне модуля, вы можете поместить файлы `.rc` в глобальный каталог:

```txt
/data/adb/initrc.d/
├── myservice.rc
└── another.rc
```

::: warning Общим файлам initrc требуется разрешение на выполнение
В отличие от каталога модуля `initrc/`, файлы в `/data/adb/initrc.d/` **должны иметь права на выполнение**, чтобы быть включенными. Неисполняемые файлы `.rc` будут пропущены без уведомления.
:::

Общие файлы `initrc.d/` обрабатываются до любых файлов RC модулей.

#### Пример

Вот пример файла `.rc`, который регистрирует кастомную службу Android:

```rc
service myservice /data/adb/modules/mymodule/bin/myservice
    user root
    group root
    disabled
    seclabel u:r:ksu:s0

on property:sys.boot_completed=1
    start myservice
```

Если этот файл помещен в `/data/adb/modules/mymodule/initrc/myservice.rc`, он зарегистрирует службу с именем `myservice` при загрузке и запустит ее по достижении `sys.boot_completed=1`.

#### Обновление вручную

Вы можете вручную запустить пересоздание `modules.rc` с помощью следующей команды (изменения вступят в силу при следующей загрузке):

```sh
ksud initrc refresh
```

::: tip

* Инъекция initrc происходит очень рано в процессе загрузки (когда init читает init.rc), **до** выполнения post-fs-data и любых скриптов модуля.
* Внедренное содержимое RC рассматривается init как часть исходного init.rc, поддерживая весь синтаксис языка Android Init (определения служб, триггеры, настройки свойств и т.д.).
* Инъекция initrc **недоступна** в **режиме late-load**, поскольку хуки системных вызовов в этом режиме не устанавливаются.
* Инъекцию RC модулей можно отключить, передав параметр `--no-custom-rc` при патчинге образа с помощью ksud.
  :::

## Установщик модулей {#module-installer}

Инсталлятор модуля KernelSU - это модуль KernelSU, упакованный в zip-файл, который может быть прошит в APP-менеджере KernelSU. Простейший установщик модуля KernelSU - это просто модуль KernelSU, упакованный в zip-файл.

```txt
module.zip
│
├── customize.sh                       <--- (Необязательно, более подробно позже)
│                                           Этот скрипт будет использоваться в update-binary
├── ...
├── ...  /* Остальные файлы модуля */
│
```

:::warning
Модуль KernelSU НЕ поддерживается для установки в пользовательское Recovery!!!
:::

### Персонализация {#customizing-installation}

Если вам необходимо настроить процесс установки модуля, то в качестве опции вы можете создать в программе установки скрипт с именем `customize.sh`. Этот скрипт будет *источником* (не исполняться!) сценария установщика модуля после извлечения всех файлов и применения стандартных разрешений и secontext. Это очень удобно, если ваш модуль требует дополнительной настройки в зависимости от ABI устройства, или вам необходимо установить специальные разрешения/секонтекст для некоторых файлов модуля.

Если вы хотите полностью контролировать и настраивать процесс установки, объявите `SKIPUNZIP=1` в файле `customize.sh`, чтобы пропустить все шаги установки по умолчанию. При этом ваш `customize.sh` будет сам отвечать за установку.

Сценарий `customize.sh` запускается в оболочке BusyBox `ash` KernelSU с включенным "Автономным режимом". Доступны следующие переменные и функции:

#### Переменные

* `KSU` (bool): переменная, отмечающая, что скрипт выполняется в окружении KernelSU, причем значение этой переменной всегда будет true. Ее можно использовать для различения KernelSU и Magisk.
* `KSU_VER` (string): строка версии текущего установленного KernelSU (например, `v0.4.0`)
* `KSU_VER_CODE` (int): код версии текущего установленного KernelSU в пользовательском пространстве (например, `10672`)
* `KSU_KERNEL_VER_CODE` (int): код версии текущей установленной KernelSU в пространстве ядра (например, `10672`)
* `BOOTMODE` (bool): в KernelSU всегда должно быть `true`.
* `MODPATH` (path): путь, по которому должны быть установлены файлы ваших модулей
* `TMPDIR` (path): место, где вы можете временно хранить файлы
* `ZIPFILE` (path): установочный zip-архив вашего модуля
* `ARCH` (string): архитектура процессора устройства. Значение: `arm`, `arm64`, `x86` или `x64`.
* `IS64BIT` (bool): `true`, если `$ARCH` имеет значение `arm64` или `x64`.
* `API` (int): уровень API (версия Android) устройства (например, `23` для Android 6.0)
* `KSU_UAPI_VER` (int): версия UAPI пользовательского пространства KernelSU (ksud) (например, `2`). Эта версия увеличивается при критических изменениях в драйвере ядра, и модули могут использовать её для проверки совместимости.
* `KSU_RUNTIME_MODE` (string): текущий режим работы KernelSU. Возможные значения: `built-in` (режим GKI, встроен в ядро), `lkm` (загружен как модуль ядра при запуске) или `late-load` (загружен как модуль ядра после загрузки).
* `KSU_LATE_LOAD` (int?): если KernelSU загружен с задержкой после загрузки системы, значение этой переменной равно `1`; в противном случае переменная не устанавливается.

::: warning
В KernelSU MAGISK_VER_CODE всегда равен 25200, а MAGISK_VER всегда равен v25.2. Пожалуйста, не используйте эти две переменные для определения того, запущен ли он на KernelSU или нет.
:::

#### Функции {#functions}

```txt
ui_print <msg>
    вывести <msg> на консоль
    Избегайте использования 'echo', так как он не будет отображаться в консоли пользовательского recovery

abort <msg>
    вывести сообщение об ошибке <msg> на консоль и завершить установку
    Избегайте использования команды 'exit', так как в этом случае будут пропущены шаги очистки завершения установки

set_perm <target> <owner> <group> <permission> [context]
    если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
    Эта функция является сокращением для следующих команд:
       chown owner.group target
       chmod permission target
       chcon context target

set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]
    если [context] не задан, то по умолчанию используется "u:object_r:system_file:s0".
    для всех файлов в <directory> будет вызвана команда:
       set_perm file owner group filepermission context
    для всех каталогов в <directory> (включая себя самого), он вызовет:
       set_perm dir owner group dirpermission context
```

## Загрузочные сценарии {#boot-scripts}

В KernelSU скрипты делятся на два типа в зависимости от режима их работы: режим post-fs-data и режим late_start service:

* режим post-fs-data
  * Эта стадия является БЛОКИРУЮЩЕЙ. Процесс загрузки приостанавливается до завершения выполнения или по истечении 10 секунд.
  * Сценарии запускаются до того, как будут смонтированы какие-либо модули. Это позволяет разработчику модулей динамически настраивать свои модули до того, как они будут смонтированы.
  * Этот этап происходит до запуска Zygote, что практически означает, что все в Android
  * **ПРЕДУПРЕЖДЕНИЕ:** использование `setprop` приведет к блокировке процесса загрузки! Вместо этого используйте `resetprop -n <prop_name> <prop_value>`.
  * Запускайте скрипты в этом режиме только в случае необходимости.
* режим обслуживания late_start
  * Эта стадия является НЕБЛОКИРУЮЩЕЙ. Ваш скрипт выполняется параллельно с остальным процессом загрузки.
  * **Это рекомендуемый этап для запуска большинства скриптов.**

В KernelSU скрипты запуска делятся на два типа по месту их хранения: общие скрипты и скрипты модулей:

* Общие скрипты
  * Размещаются в файлах `/data/adb/post-fs-data.d` или `/data/adb/service.d`.
  * Выполняется только в том случае, если скрипт установлен как исполняемый (`chmod +x script.sh`)
  * Скрипты в `post-fs-data.d` выполняются в режиме post-fs-data, а скрипты в `service.d` - в режиме late_start service.
  * Модули не должны **НЕ** добавлять общие скрипты при установке
* Скрипты модуля
  * Размещаются в отдельной папке модуля
  * Выполняются только в том случае, если модуль включен
  * `post-fs-data.sh` запускается в режиме post-fs-data, а `service.sh` - в режиме late_start service.

Все загрузочные скрипты будут выполняться в оболочке BusyBox `ash` от KernelSU с включенным "Автономным режимом".

## Режим late-load {#late-load-mode}

Помимо стандартного процесса загрузки, описанного выше, KernelSU поддерживает **режим late-load** для сценариев LKM (загружаемый модуль ядра). В этом режиме модуль ядра KernelSU загружается **после полной загрузки системы**, а не во время процесса init.

### Когда происходит late-load?

Late-load запускается командой `ksud late-load`. Эта команда:

1. Определяет текущую версию KMI и загружает соответствующий `kernelsu.ko` из встроенных ресурсов.
2. Выполняет инициализацию модуля (правила SELinux, список разрешений, функции и т.д.), которая обычно происходит во время загрузки.

Поскольку система уже полностью запущена, некоторые механизмы времени загрузки недоступны или не нужны.

### Отличия от стандартной загрузки

| Поведение | Стандартная загрузка | Режим late-load |
|-----------|:---:|:---:|
| Модуль ядра загружен init (PID 1) | Да | Нет (загружен после загрузки) |
| Хуки kprobe ksud (execve/read/fstat/input) | Да | Пропущены |
| Обнаружение безопасного режима (клавиша громкости) | Да | Всегда отключено |
| Захват журнала загрузки (logcat/dmesg) | Да | Пропущен |
| Проверка сосуществования с Magisk | Да | Пропущена |
| Событие `post-fs-data` отправлено ядру | Да | Пропущено |
| Событие `boot-completed` отправлено ядру | Да | Установлено напрямую при инициализации |
| Скрипты `post-fs-data.sh` / `post-fs-data.d/` | Да | Заменены этапом `late-load` |
| Загрузка `system.prop` | Да | Да |
| Монтирование OverlayFS (metamodule) | Да | Да |
| Скрипты `post-mount.sh` / `post-mount.d/` | Да | Да |
| Скрипты `service.sh` / `service.d/` | Да | Да |
| Скрипты `boot-completed.sh` / `boot-completed.d/` | Да | Да |
| Переменная окружения `KSU_LATE_LOAD` | Не установлена | Установлена в `1` |
| Флаг info ядра `0x4` | Не установлен | Установлен |

### Порядок выполнения скриптов

В режиме late-load порядок выполнения скриптов следующий:

```txt
ksud late-load:
  1. Загрузить kernelsu.ko (если ещё не загружен)
  2. Извлечь бинарные файлы, обработать обновления модулей, загрузить правила SELinux, инициализировать функции
  3. Выполнить скрипты late-load.d/ и скрипты late-load модулей (блокирующе)
  4. Загрузить system.prop (resetprop -n)
  5. Выполнить скрипт монтирования metamodule (OverlayFS)
  6. Выполнить скрипты post-mount.d/ и post-mount.sh модулей (блокирующе)
  7. Выполнить скрипты service.d/ и service.sh модулей (неблокирующе)
  8. Выполнить скрипты boot-completed.d/ и boot-completed.sh модулей (неблокирующе)
```

### Скрипты, специфичные для late-load

Модули могут предоставить скрипт `late-load.sh`, который выполняется **только** в режиме late-load, как замена `post-fs-data.sh`. Этот скрипт выполняется до монтирования OverlayFS, аналогично `post-fs-data.sh` в стандартном потоке.

Кроме того, общие скрипты можно размещать в `/data/adb/late-load.d/` для выполнения на этом этапе.

### Обнаружение режима late-load в скриптах

Модули могут определить режим late-load, проверив переменную окружения `KSU_LATE_LOAD`:

```sh
if [ "$KSU_LATE_LOAD" = "1" ]; then
    # Работа в режиме late-load
    echo "Late-load mode detected"
fi
```

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