Android Init Language由五个元素组成:Acttions、Commands、Services、Options和Imports。
Actions和Services隐式声明了一个新的section。所以的Commands和Options都属于最近声明的section。
Services具有唯一的名称,如果重名会报错。
Actions
Actions被视为Commands的序列。
Actions有一个trigger指明什么时候action被执行。当有和trigger事件匹配的事件发生时,这个action会被添加到待执行队列的尾部(除非它已经存在于队列中)。
Actions形如:
on <trigger> [&& <trigger>]*<command><command><command>...
Services
Services是init启动或重启时执行的程序。形如:
service <name> <pathname> [ <argument> ]*<option><option><option>...
Options
Options是Services的修饰符,表示如何或何时运行service。
具体有哪些Options,详见:init/README.md (googlesource.com)
Commands
具体有哪些Commands,详见:init/README.md (googlesource.com)
 在代码中(/system/core/init/builtins.cpp)中,有Commands与函数的映射
// Builtin-function-map start
const BuiltinFunctionMap& GetBuiltinFunctionMap() {constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();// clang-format offstatic const BuiltinFunctionMap builtin_functions = {{"bootchart",               {1,     1,    {false,  do_bootchart}}},{"chmod",                   {2,     2,    {true,   do_chmod}}},{"chown",                   {2,     3,    {true,   do_chown}}},{"class_reset",             {1,     1,    {false,  do_class_reset}}},{"class_restart",           {1,     2,    {false,  do_class_restart}}},{"class_start",             {1,     1,    {false,  do_class_start}}},{"class_stop",              {1,     1,    {false,  do_class_stop}}},{"copy",                    {2,     2,    {true,   do_copy}}},{"copy_per_line",           {2,     2,    {true,   do_copy_per_line}}},{"domainname",              {1,     1,    {true,   do_domainname}}},{"enable",                  {1,     1,    {false,  do_enable}}},{"exec",                    {1,     kMax, {false,  do_exec}}},{"exec_background",         {1,     kMax, {false,  do_exec_background}}},{"exec_start",              {1,     1,    {false,  do_exec_start}}},{"export",                  {2,     2,    {false,  do_export}}},{"hostname",                {1,     1,    {true,   do_hostname}}},{"ifup",                    {1,     1,    {true,   do_ifup}}},{"init_user0",              {0,     0,    {false,  do_init_user0}}},{"insmod",                  {1,     kMax, {true,   do_insmod}}},{"installkey",              {1,     1,    {false,  do_installkey}}},{"interface_restart",       {1,     1,    {false,  do_interface_restart}}},{"interface_start",         {1,     1,    {false,  do_interface_start}}},{"interface_stop",          {1,     1,    {false,  do_interface_stop}}},{"load_exports",            {1,     1,    {false,  do_load_exports}}},{"load_persist_props",      {0,     0,    {false,  do_load_persist_props}}},{"load_system_props",       {0,     0,    {false,  do_load_system_props}}},{"loglevel",                {1,     1,    {false,  do_loglevel}}},{"mark_post_data",          {0,     0,    {false,  do_mark_post_data}}},{"mkdir",                   {1,     6,    {true,   do_mkdir}}},// TODO: Do mount operations in vendor_init.// mount_all is currently too complex to run in vendor_init as it queues action triggers,// imports rc scripts, etc.  It should be simplified and run in vendor_init context.// mount and umount are run in the same context as mount_all for symmetry.{"mount_all",               {0,     kMax, {false,  do_mount_all}}},{"mount",                   {3,     kMax, {false,  do_mount}}},{"perform_apex_config",     {0,     0,    {false,  do_perform_apex_config}}},{"umount",                  {1,     1,    {false,  do_umount}}},{"umount_all",              {0,     1,    {false,  do_umount_all}}},{"update_linker_config",    {0,     0,    {false,  do_update_linker_config}}},{"readahead",               {1,     2,    {true,   do_readahead}}},{"remount_userdata",        {0,     0,    {false,  do_remount_userdata}}},{"restart",                 {1,     2,    {false,  do_restart}}},{"restorecon",              {1,     kMax, {true,   do_restorecon}}},{"restorecon_recursive",    {1,     kMax, {true,   do_restorecon_recursive}}},{"rm",                      {1,     1,    {true,   do_rm}}},{"rmdir",                   {1,     1,    {true,   do_rmdir}}},{"setprop",                 {2,     2,    {true,   do_setprop}}},{"setrlimit",               {3,     3,    {false,  do_setrlimit}}},{"start",                   {1,     1,    {false,  do_start}}},{"stop",                    {1,     1,    {false,  do_stop}}},{"swapon_all",              {0,     1,    {false,  do_swapon_all}}},{"enter_default_mount_ns",  {0,     0,    {false,  do_enter_default_mount_ns}}},{"symlink",                 {2,     2,    {true,   do_symlink}}},{"sysclktz",                {1,     1,    {false,  do_sysclktz}}},{"trigger",                 {1,     1,    {false,  do_trigger}}},{"verity_update_state",     {0,     0,    {false,  do_verity_update_state}}},{"wait",                    {1,     2,    {true,   do_wait}}},{"wait_for_prop",           {2,     2,    {false,  do_wait_for_prop}}},{"write",                   {2,     2,    {true,   do_write}}},};// clang-format onreturn builtin_functions;
}
Imports
形如:
import <path>
Import有它自己的section,不是Actions的一部分。
Import用来解析init配置文件、扩展当前配置。如果 
Triggers(触发器)
触发器用来匹配某类事件并触发aciton发生。
触发器分为事件触发器和属性触发器。
事件触发器由“trigger” Command或init程序的QueueEventTrigger()函数触发。
属性触发器是在属性改变时触发。
一个Action可以有多个属性触发器,但只能有一个事件触发器。
具体有哪些触发器,详见:init/README.md (googlesource.com)
init.rc举例
下面节选一下init.rc文件中怎么写的,先感受一下
# Copyright (C) 2012 The Android Open Source Project
#
# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.
#import /init.environ.rc
import /system/etc/init/hw/init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /system/etc/init/hw/init.usb.configfs.rc
import /system/etc/init/hw/init.${ro.zygote}.rc......# Mount filesystems and start core system services.
on late-inittrigger early-fs# Mount fstab in init.{$device}.rc by mount_all command. Optional parameter# '--early' can be specified to skip entries with 'latemount'.# /system and /vendor must be mounted by the end of the fs stage,# while /data is optional.trigger fstrigger post-fs# Mount fstab in init.{$device}.rc by mount_all with '--late' parameter# to only mount entries with 'latemount'. This is needed if '--early' is# specified in the previous mount_all command on the fs stage.# With /system mounted and properties form /system + /factory available,# some services can be started.trigger late-fs# Now we can mount /data. File encryption requires keymaster to decrypt# /data, which in turn can only be loaded when system properties are present.trigger post-fs-data# Should be before netd, but after apex, properties and logging is available.trigger load_bpf_programs# Now we can start zygote for devices with file based encryptiontrigger zygote-start# Remove a file to wake up anything waiting for firmware.trigger firmware_mounts_completetrigger early-boottrigger boot......service boringssl_self_test32 /system/bin/boringssl_self_test32reboot_on_failure reboot,boringssl-self-check-failedstdio_to_kmsg# Explicitly specify that boringssl_self_test32 doesn't require any capabilitiescapabilitiesuser nobody