Android Init 语言包含四类主要的语句,分别是动作、命令、服务和选项。
所有这些都是面向行的,由用空格分隔的标记组成。C 样式的反斜杠转义符可用于将空格插入标记。也可以使用双引号来防止空格将文本分成多个标记。反斜杠是一行中的最后一个字符时,可用于折行。
以#开头的行是注释。
Action 和 Service 隐式声明一个新的 Section。 所有命令(Command)或选项(Option)都属于最近声明的 Section。 首个 Section 之前的命令或选项将被忽略。
Action 和 Service 具有唯一的名称。 如果第二个 Action 或 Service 声明为与现有的 Action 或 Service 相同的名称,则将其忽略为错误。
一、Action
Action 被称为命令序列。 Action 具有触发器,用于确定何时应执行该 Action 。当发生与某个 Action 的触发器匹配的事件时,该 Action 将添加到要执行的队列的尾部(除非它已在队列中)。队列中的每个 Action 都按顺序出队,并且该 Action 中的每个命令都按顺序执行。 Init 进程同时处理命令执行之间的其他活动(设备创建/销毁、属性设置和进程重新启动)。
Action 格式如下:
on <trigger>
<command>
<command>
<command>
二、Service
Service 是用于 Init 启动的程序,它们在退出时(可选)重新启动。
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
三、Option
选项是服务的修改器。它们会影响 Init 运行服务的方式和时间。
3.1 critical
这是一项关键设备服务。如果在四分钟内退出四次以上,设备将重新启动进入 recovery (恢复)模式。
3.2 disabled
该服务不会自动从其类开始。必须通过名称显式启动。
3.3 setenv <name> <value>
在启动的过程中,将环境变量 设置为 。
3.4 socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
创建一个名为 /dev/socket/<name> 的 Unix 域套接字并传递其 fd 到启动进程。
<type> 必须是“dgram”、“stream”和“seqpacket”。
用户和组默认为 0。
“seclabel” 是套接字的 SELinux 安全上下文。它默认为服务安全上下文,如 seclabel 或基于服务可执行文件安全性上下文进行计算。
3.5 user <username>
执行此服务前,修改为用户名 <username>。
当前默认为 root。
当前,如果你的进程需要 Linux 功能,那么你不能使用此命令。相反,你必须在仍然是 root 用户的情况下请求进程内的功能,然后将其降到所需的 uid。
3.6 group <groupname> [ <groupname> ]*
执行此服务之前,将组切换为 <groupname>。 除了第一个组(必需的)之外的其他组名用于设置进程的补充组(通过 setgroups())。
当前默认为root。
3.7 seclabel <seclabel>
执行此服务前更改为 <seclabel>。
主要用于从 rootfs 运行的服务,如 ueventd、adbd。系统分区上的服务可以根据其文件安全上下文使用策略定义的转换。如果没有指定,并且在策略中没有定义转换,则默认为 Init 上下文。
3.8 oneshot
退出服务时不要重新启动它。
3.9 class <name>
指定服务的类名。命名类中的所有服务都可以一起启动或停止。如果未通过 class 选项指定服务类名,则该服务位于“default”类中。
3.10 onrestart
服务重启时执行的命令。
3.11 writepid <file…>
fork 时将子进程的 pid 写入给定文件。
四、Trigger
触发器是可用于匹配某些类型的事件并用于引起操作发生的字符串。
4.1 boot
这是 Init 启动时(加载 /init.conf 之后)将发生的第一个触发器。
4.2 <name>=<value>
当属性 <name> 设置为特定值 <value> 时,将发生这种形式的触发器。
也可以测试多个属性以执行一组命令。例如:
on property:test.a=1 && property:test.b=1
setprop test.c 1
仅当 test.a = 1 和 test.b = 1 时,以上片段才将 test.c 设置为 1。
五、Command
5.1 bootchart_init
如果已配置,启动引导图。这包含在默认的 init.rc 中。
5.2 chmod <octal-mode> <path>
更改文件访问权限。
5.3 chown <owner> <group> <path>
更改文件所有者和组。
5.4 class_start <serviceclass>
启动指定类的所有服务(如果尚未运行)。
5.5 class_stop <serviceclass>
如果当前正在运行,停止并禁用指定类的所有服务。
5.6 class_reset <serviceclass>
如果当前正在运行指定类的所有服务,停止它们,而不需要禁用它们。稍后可以使用 class_start 重新启动它们。
5.7 copy <src> <dst>
复制文件。与写入类似,但对于二进制/大量数据很有用。
5.8 domainname <name>
设置域名(domain)。
5.9 enable <servicename>
将禁用的服务转变为启用的服务,就像该服务未指定禁用一样。
如果假设该服务正在运行,则将立即启动。
通常在引导加载程序设置一个变量时使用,该变量指示应在需要时启动特定的服务。例如:
on property:ro.boot.myfancyhardware=1
enable my_fancy_service_for_my_fancy_hardware
5.10 exec [ <seclabel> [ <user> [ <group> ]* ] ] -- <command> [ <argument> ]*
用给定参数 fork 并执行命令。该命令在“–”之后开始,以便提供可选的安全上下文、用户和补充组。在完成此命令之前,将不会运行其他命令。<seclabel> 可以是“-”表示默认值。
5.11 export <name> <value>
在全局环境中将环境变量 <name> 设置为等于 <value>(将由执行此命令后启动的所有进程继承)。
5.12 hostname <name>
设置主机名。
5.13 ifup <interface>
使网络接口 <interface> 在线。
5.14 import <filename>
解析一个 init 配置文件,扩展当前配置。
5.15 insmod <path>
将模块安装在 <path>。
5.16 load_all_props
从 /system,/vendor 等加载属性。这包含在默认的 init.rc 中。
5.17 load_persist_props
解密 /data 后,加载持久属性。这包含在默认的 init.rc 中。
5.18 loglevel <level>
将内核日志级别设置为 level。属性在 <level> 中展开。
5.19 mkdir <path> [mode] [owner] [group]
在 <path> 中创建一个目录,可以选择使用给定的模式、所有者和组。 如果未提供,则使用权限 755 创建目录,该目录由 root 用户和 root 组拥有。如果该目录已经存在,则将更新模式、所有者和组。
5.20 mount_all <fstab>
在给定的 fs_mgr 格式 fstab 上调用 fs_mgr_mount_all。
5.21 mount <type> <device> <dir> [ <flag> ]* [<options>]
尝试将命名设备挂载在目录 <dir> 中
<device> 可以采用 mtd@name 的形式来指定 mtd 块设备名称。
<flag> 包括“ ro”,“ rw”,“remount”,“ noatime”…
<options> 包括“ barrier=1”,“ noauto_da_alloc”,“ discard”…逗号分隔的字符串,例如:barrier=1,noauto_da_alloc
5.22 powerctl
内部实现细节用于响应对“sys.powerctl”系统属性的更改,用于实现重启。
5.23 restart <service>
像停止一样,但不禁用服务。
5.24 restorecon <path> [ <path> ]*
将 <path> 命名的文件还原到 file_contexts 配置中指定的安全上下文。由 init.rc 创建的目录不需要,因为这些目录会由 Init 自动正确标记。
5.25 restorecon_recursive <path> [
]*
将由 <path> 命名的目录树递归还原到 file_contexts 配置中指定的安全上下文。
5.26 rm <path>
在给定路径上调用 unlink(2)。你可能要使用“exec – rm …”代替(前提是已经安装了系统分区)。
5.27 rmdir <path>
在给定路径上调用 rmdir(2)。
5.28 setprop <name> <value>
将系统属性 <name> 设置为 <value>。
5.29 setrlimit <resource> <cur> <max>
设置资源的 rlimit(资源限制)。
5.23 start <service>
如果服务尚未运行,启动它。
5.24 stop <service>
如果服务当前正在运行,停止该服务。
5.25 swapon_all <fstab>
在给定的 fstab 文件上调用 fs_mgr_swapon_all。
5.26 symlink <target> <path>
在 <path> 创建一个值为 <target> 的符号链接
5.27 sysclktz <mins_west_of_gmt>
设置系统时钟基准(如果系统时钟在 GMT 中计时,则为 0)
5.28 trigger <event>
触发事件。用于将另一个 Action 中的一个 Action 排队。
5.29 verity_load_state
内部实现细节,用于加载 dm-verity 状态。
5.30 verity_update_state <mount_point>
内部实现详细信息,用于更新 dm-verity 状态并设置分区。由于 fs_mgr 本身无法直接设置它们,因此重新安装了adb 使用的 <mount_point>.verified 属性。
5.31 wait <path> [ <timeout> ]
轮询给定文件的存在性,并在找到文件或超时时返回。如果未指定超时,则当前默认为五秒钟。
5.32 write <path> <content>
在
六、init.zygote32.rc
system/core/rootdir/init.zygote32.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks
对照上面对 service 的解读,首先这个 service 的名称是 zygote,路径名是:/system/bin/app_process,使用的参数分别是 “-Xzygote”、“/system/bin”、“–zygote”和“–start-system-server”。
指定服务的类名是 main,用于统一控制服务启动和停止用。
启动一个 socket 名为 zygote,类型为 stream,权限为 660 代表拥有者有读、写权限,属组用户也有读、写权限,用户是 root,组为 system。
服务重启时执行的命令:
write /sys/android_power/request_state wake
write /sys/power/state on
restart media
restart netd
在 /sys/android_power/request_state 中打开文件,然后使用 write(2) 向其中写入“wake”;
在 /sys/power/state 中打开文件,然后使用 write(2) 向其中写入“on”;
重启 media 服务;
重启 netd 服务。
writepid /dev/cpuset/foreground/tasks
fork 时将子进程的 pid 写入 /dev/cpuset/foreground/tasks。