Android Init语言包含五种主要的语句类:Actions, Commands, Services, Options, and Imports.
所有这些都是面向行的,由用空格分隔的标记组成。C样式的反斜杠转义符可用于将空格插入token。也可以使用双引号来防止空格将文本分成多个标记。反斜杠是一行中的最后一个字符时,可用于折行。
以#开头的行(允许前导空格)是注释。
可以使用语法$ {property.name} 扩展系统属性。这也适用于需要连接的上下文,例如import /init.recovery.${ro.hardware}.rc 。
Actions 和Services隐式声明一个新部分。所有命令或选项都属于最近声明的部分。第一个section 之前的命令或选项将被忽略。
Services具有唯一的名称。如果使用与现有Services相同的名称定义了另一个Services,则将其忽略并记录一条错误消息。
Init .rc Files
带有.rc文件扩展名的纯文本文件使用init语言。通常,在系统上的多个位置中有多个这样的对象,如下所述。
/init.rc是主要的.rc文件,由init可执行文件在执行开始时加载。它负责系统的初始设置。
在加载主/init.rc之后,Init会立即加载/ {system,vendor,odm} / etc / init /目录中包含的所有文件。此文件的“导入”部分中对此进行了更详细的说明。
没有第一阶段安装机制的旧式设备以前能够在mount_all期间导入初始化脚本,但是已弃用并且不允许在Q之后启动设备。
这些目录的目录是:
- /system/etc/init /用于核心系统项,例如SurfaceFlinger,MediaService和logd。
- /vendor/etc/init /用于SoC供应商项目,例如核心SoC功能所需的操作或守护程序。
- / odm / etc/init /用于设备制造商的产品,例如运动传感器或其他外围功能所需的操作或守护程序。
所有二进制文件驻留在系统,供应商或odm分区上的服务都应将其服务条目放置在相应的init .rc文件中,该文件位于它们所在分区的/ etc / init /目录中。有一个构建系统宏LOCAL_INIT_RC可以为开发人员处理。每个init .rc文件还应包含与其服务关联的所有操作。
一个示例是位于system / core / logcat目录中的userdebug logcatd.rc和Android.mk文件。Android.mk文件中的LOCAL_INIT_RC宏在构建过程中将logcatd.rc放在/ system / etc / init /中。在适当的情况下,init会在mount_all命令期间加载logcatd.rc,并允许运行服务并使操作排队。
根据先前的守护程序对init .rc文件进行这种分解,比以前使用的整体式init .rc文件更可取。这种方法确保了init读取的唯一服务条目和init执行的唯一动作与实际上二进制文件存在于文件系统上的服务相对应,而整体init .rc文件则不是这种情况。当将多个服务添加到系统时,这还将有助于解决合并冲突,因为每个服务都将进入一个单独的文件中。
Actions
Actions 被称为commands序列。Actions 具有触发器,用于确定何时执行动作。当发生与某个动作的触发器匹配的事件时,该动作将添加到要执行的队列的尾部(除非它已经在队列中)。
队列中的每个动作都按顺序出队,并且该动作中的每个命令都按顺序执行。Init处理活动中命令执行之间的其他活动(设备创建/销毁,属性设置,进程重新启动)。
Actions采取以下形式:
on <trigger> [&& <trigger>]*
<command>
<command>
<command>
Actions 将被添加到队列中,并根据解析包含它们的文件的顺序执行(请参见“Imports”部分),然后在单个文件中顺序执行。
例如,如果文件包含:
on boot
setprop a 1
setprop b 2
on boot && property:true=true
setprop c 1
setprop d 2
on boot
setprop e 1
setprop f 2
然后,当发生启动触发器并假设属性true 等于true时,执行的命令顺序将为:
setprop a 1
setprop b 2
setprop c 1
setprop d 2
设定值1
setprop f 2
Services
Services是用于启动的程序,它们在退出时(可选)重新启动。服务采取以下形式:
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
Options
Options是服务的修改器。它们会影响init运行服务的方式和时机。
capabilities [ <capability>\* ]
执行此服务时设置capabilities。“capability”应该是没有“ CAP_”前缀的Linux功能,例如“ NET_ADMIN”或“ SETPCAP”。有关Linuxcapabilities的list,请参见http://man7.org/linux/man-pages/man7/capabilities.7.html。如果未提供任何capabilities,则即使该服务以root身份运行,也会从该服务中删除所有功能。
class <name> [ <name>\* ]
指定服务的类名称。命名类中的所有服务都可以一起启动或停止。如果未通过class选项指定服务,则该服务位于“默认”类中。除(必需)第一个之外的其他类名用于对服务进行分组。该动画类应包括所有必要的两种开机动画和关机动画服务。由于这些服务可以在启动过程中很早就启动,并且可以运行到关闭的最后一个阶段,因此不能保证对/ data分区的访问。这些服务可以检查/ data下的文件,但不能使文件保持打开状态,并且在/ data不可用时可以正常工作。
console [<console>]
该服务需要一个console 。可选的第二个参数选择特定的控制台而不是默认的console 。可以通过设置“ androidboot.console”内核参数来更改默认的“ / dev / console”。在所有情况下,都应省略开头的“ / dev /”,因此将“ / dev / tty0”指定为“ console tty0”。此选项将stdin,stdout和stderr连接到console。它与stdio_to_kmsg选项互斥,该选项仅将stdout和stderr连接到kmsg。
critical
这是一项设备关键service。如果在四分钟内或在引导完成之前退出四次以上,则设备将重新引导到引导加载程序中。
disabled
该服务不会自动从其类开始。必须通过名称或接口名称显式启动它。
enter_namespace <type> <path>
输入位于path 处的type 类型的名称空间。仅支持类型设置为“ net”的网络名称空间。注意,只能输入给定类型的一个名称空间。
file <path> <type>
打开文件路径,并将其fd传递给启动的进程。类型必须为“ r”,“ w”或“ rw”。有关本机可执行文件,请参见libcutils android_get_control_file()。
group <groupname> [ <groupname>\* ]
执行此服务之前,请更改为“ groupname”。除了(必需的)第一个组之外的其他组名用于设置进程的补充组(通过setgroups())。当前默认为root。(???可能应该默认为nobody)
interface <interface name> <instance name>
将此服务与其提供的HIDL服务列表相关联。接口名称必须是标准名称,而不是值名称。例如,它用于允许hwservicemanager延迟启动服务。提供多个接口时,应多次使用此标记。例如:接口vendor.foo.bar@1.0 :: IBaz默认
ioprio <class> <priority>
通过SYS_ioprio_set syscall设置此服务的IO优先级和IO优先级类别。class 必须是“ rt”,“ be”或“ idle”之一。优先级必须是0到7之间的整数。
keycodes <keycode> [ <keycode>\* ]
设置将触发此服务的键码。如果一次按下与传递的键码对应的所有键,则服务将启动。通常用于启动错误报告服务。
该选项可以采用属性而不是键码列表。在这种情况下,仅提供一个选项:典型属性扩展格式的属性名称。该属性必须包含逗号分隔的键码值列表或文本“ none”,以指示此服务不响应键码。
例如,键码$ {some.property.name:-none} ,其中some.property.name扩展为“ 123,124,125”。由于键码是在初始化的早期就处理的,因此只能使用PRODUCT_DEFAULT_PROPERTY_OVERRIDES属性。
memcg.limit_in_bytes <value>
and memcg.limit_percent <value>
将子级的memory.limit_in_bytes设置为limit_in_bytes 字节和limit_percent 的最小值,该值解释为设备物理内存大小的百分比(仅在安装了memcg的情况下)。值必须等于或大于0。
memcg.limit_property <value>
将子级的memory.limit_in_bytes设置为指定属性的值(仅在安装了memcg的情况下)。此属性将覆盖通过memcg.limit_in_bytes 和memcg.limit_percent 指定的值。
memcg.soft_limit_in_bytes <value>
将子级的memory.soft_limit_in_bytes设置为指定值(仅在安装了memcg的情况下),该值必须等于或大于0。
memcg.swappiness <value>
将child的memory.swappiness设置为指定值(仅在安装了memcg的情况下),该值必须等于或大于0。
namespace <pid|mnt>
forking服务时,输入新的PID或mount名称空间。
oneshot
退出服务时不要重新启动它。
onrestart
服务重启时执行命令(见下文)。
oom_score_adjust <value>
将child的/ proc / self / oom_score_adj设置为指定的值,该值的范围必须为-1000到1000。
override
指示此服务定义旨在覆盖具有相同名称的服务的先前定义。这通常意味着/ odm上的服务将覆盖/ vendor上定义的服务。初始化使用此关键字解析的最后一个服务定义是将用于此服务的服务定义。请密切注意init.rc文件的解析顺序,因为出于向后兼容的原因,它具有一些特殊性。该文件的“导入”部分具有有关订单的更多详细信息。
priority <priority>
调度服务进程的优先级。此值的范围必须为-20到19。默认优先级为0。通过setpriority()设置优先级。
reboot_on_failure <target>
如果无法启动此过程,或者该过程以CLD_EXITED以外的退出代码或非0的状态终止,请使用target中指定的目标重新启动系统。目标采用与sys.powerctl参数相同的格式。特别适合与内置exec_start 一起使用,以便在引导过程中进行任何必需的检查。
restart_period <seconds>
如果非oneshot服务退出,它将在其开始时间加上此时间段后重新启动。默认为5秒以限制崩溃服务的速率。对于本应定期运行的服务,可以增加此数量。例如,可以将其设置为3600以指示该服务应每小时运行一次,或者可以将其设置为86400以指示该服务应每天运行一次。
rlimit <resource> <cur> <max>
这会将给定的rlimit应用于服务。rlimit由子进程继承,因此这有效地将给定的rlimit应用于此服务启动的进程树。它的解析类似于下面指定的setrlimit命令。
seclabel <seclabel>
执行此服务前,请更改为“ seclabel”。主要供从rootfs运行的服务使用,例如ueventd,adbd。系统分区上的服务可以根据其文件安全性上下文使用策略定义的过渡。如果未指定并且策略中未定义任何过渡,则默认为init上下文。
setenv <name> <value>
在启动的过程中将环境变量名称设置为value 。
shutdown <shutdown_behavior>
设置服务进程的关闭行为。如果未指定此选项,则在关闭过程中通过使用SIGTERM和SIGKILL终止服务。在关机期间,除非shutdown超时,否则shutdown_behavior为“ critical”的服务不会被杀死。当关机超时时,即使标记为“紧急关机”的服务也将被杀死。当关闭启动时,标有“关闭严重”的服务未运行时,它将启动。
sigstop
在调用exec之前,立即将SIGSTOP发送到服务。这是用于调试。有关如何使用它的信息,请参见下面的调试部分。
socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
创建一个名为/ dev / socket / name 的UNIX域套接字,并将其fd传递给启动的进程。类型必须为“ dgram”,“ stream”或“ seqpacket”。类型可以以“ + passcred” 结尾,以在套接字上启用SO_PASSCRED。用户和组的默认值为0。“ seclabel”是套接字的SELinux安全上下文。它默认为服务安全上下文,由seclabel指定或根据服务可执行文件安全上下文进行计算。有关本机可执行文件,请参见libcutils android_get_control_socket()。
stdio_to_kmsg
将stdout和stderr重定向到/ dev / kmsg_debug。这对于在早期启动期间不使用本机Android日志记录以及我们要捕获其日志消息的服务很有用。仅在启用/ dev / kmsg_debug时才启用此功能,而仅在userdebug和eng构建中启用。这与console选项互斥,后者将stdin连接到给定的控制台。
task_profiles <profile> [ <profile>\* ]
设置流程在分叉时的任务配置文件。旨在替代使用writepid选项将进程移入cgroup。
timeout_period <seconds>
提供超时后,服务将被终止。这里使用oneshot关键字,因此oneshot服务不会自动重新启动,但是所有其他服务都可以。这对于创建结合了上述的restart_period选项的定期服务特别有用。
updatable
标记该服务可以在启动顺序中稍后由APEXes覆盖(通过'override'选项)。在激活APEX之前启动具有可更新选项的服务时,执行将延迟到激活完成为止。未标记为可更新的服务不能被APEX覆盖。
user <username>
执行此服务之前,请更改为“用户名”。当前默认为root。(???可能默认为no)从Android M开始,即使进程需要Linux功能,也应使用此选项。以前,要获得Linux功能,进程将需要以root用户身份运行,请求功能,然后降至所需的uid。通过fs_config提供了一种新机制,该机制允许设备制造商向应使用的文件系统上的特定二进制文件添加Linux功能。在http://source.android.com/devices/tech/config/filesystem.html上描述了此机制。使用这种新机制时,进程可以使用用户选项选择所需的uid,而无需以root用户身份运行。从Android O开始,进程还可以直接在其.rc文件中请求功能。请参阅下面的“功能”选项。
writepid <file> [ <file>\* ]
分支时将孩子的pid写入给定文件。cgroup / cpuset用法的含义。如果未在/ dev / cpuset /下指定任何文件,但是将系统属性'ro.cpuset.default'设置为非空的cpuset名称(例如'/ foreground'),则将pid写入文件/ dev / cpuset / cpuset_name /任务。使用此选项将进程移入cgroup已过时。请改用task_profiles选项。
Triggers
触发器是可用于匹配某些类型的事件并用于引起操作发生的字符串。
触发器分为事件触发器和属性触发器。
事件触发器是由'trigger'命令或init可执行文件中的QueueEventTrigger()函数触发的字符串。这些采用简单字符串的形式,例如“ boot”或“ late-init”。
属性触发器是当命名属性将值更改为给定新值或命名属性将值更改为任何新值时触发的字符串。它们分别采用'property:='和'property:= *'的形式。在初始化的初始引导阶段还会额外评估并触发属性触发器。
一个动作可以有多个属性触发器,但只能有一个事件触发器。
例如:在启动时&& property:a = b 定义仅在发生'boot'事件触发器且属性a等于b时执行的操作。
on property:a = b && property:c = d 定义了一个执行了三次的动作:
- 在初始引导期间,如果属性a = b和属性c = d。
- 每当属性a转换为值b时,属性c已经等于d。
- 每当属性c转换为值d时,而属性a已经等于b。
Commands
bootchart [start|stop]
Start/stop bootcharting. These are present in the default init.rc files, but bootcharting is only active if the file /data/bootchart/enabled exists; otherwise bootchart start/stop are no-ops.
开始/停止引导。这些文件存在于默认的init.rc文件中,但只有在/ data / bootchart / enabled文件存在的情况下,bootcharting才处于活动状态。否则,引导图开始/停止是无操作的。
chmod <octal-mode> <path>
Change file access permissions.
更改文件访问权限。
chown <owner> <group> <path>
Change file owner and group.
更改文件所有者和组。
class_start <serviceclass>
Start all services of the specified class if they are not already running. See the start entry for more information on starting services.
启动指定类的所有服务(如果尚未运行)。有关启动服务的更多信息,请参见启动条目。
class_start_post_data <serviceclass>
Like
class_start
, but only considers services that were started after /data was mounted, and that were running at the timeclass_reset_post_data
was called. Only used for FDE devices.与class_start类似,但仅考虑在/ data挂载后启动的服务,以及在class_reset_post_data 被调用时正在运行的服务。仅用于FDE设备。
class_stop <serviceclass>
Stop and disable all services of the specified class if they are currently running.
如果当前正在运行,请停止并禁用指定类的所有服务。
class_reset <serviceclass>
Stop all services of the specified class if they are currently running, without disabling them. They can be restarted later using
class_start
.如果当前正在运行指定类的所有服务,请停止它们,而不禁用它们。稍后可以使用class_start 重新启动它们。
class_reset_post_data <serviceclass>
Like
class_reset
, but only considers services that were started after /data was mounted. Only used for FDE devices.与class_reset类似,但仅考虑在/ data挂载后启动的服务。仅用于FDE设备。
class_restart <serviceclass>
Restarts all services of the specified class.
重新启动指定类的所有服务。
copy <src> <dst>
Copies a file. Similar to write, but useful for binary/large amounts of data. Regarding to the src file, copying from symbolic link file and world-writable or group-writable files are not allowed. Regarding to the dst file, the default mode created is 0600 if it does not exist. And it will be truncated if dst file is a normal regular file and already exists.
复制文件。与写入类似,但对于二进制/大量数据很有用。关于src文件,不允许从符号链接文件以及世界可写或组可写文件中进行复制。关于dst文件,如果创建的默认模式不存在,则默认值为0600。如果dst文件是一个普通的常规文件并且已经存在,它将被截断。
domainname <name>
Set the domain name.
设置domain。
enable <servicename>
Turns a disabled service into an enabled one as if the service did not specify disabled. If the service is supposed to be running, it will be started now. Typically used when the bootloader sets a variable that indicates a specific service should be started when needed. E.g.
将禁用的服务转变为启用的服务,就像该服务未指定禁用一样。如果该服务正在运行,则将立即启动。通常在引导加载程序设置一个指示应在需要时启动特定服务的变量时使用。例如
on property:ro.boot.myfancyhardware=1
enable my_fancy_service_for_my_fancy_hardware
exec [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]
Fork and execute command with the given arguments. The command starts after “--” so that an optional security context, user, and supplementary groups can be provided. No other commands will be run until this one finishes. seclabel can be a - to denote default. Properties are expanded within argument. Init halts executing commands until the forked process exits.
用给定参数分叉并执行命令。该命令在“-”之后开始,以便提供可选的安全上下文,用户和补充组。在完成此命令之前,将不会运行其他命令。seclabel 可以是-表示默认值。属性在arguments 中扩展。初始化将暂停执行命令,直到分支进程退出。
exec_background [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]
Fork and execute command with the given arguments. This is handled similarly to the
exec
command. The difference is that init does not halt executing commands until the process exits forexec_background
.用给定参数分叉并执行命令。这与exec 命令类似。区别在于init直到进程退出exec_background 才停止执行命令。
exec_start <service>
Start a given service and halt the processing of additional init commands until it returns. The command functions similarly to the
exec
command, but uses an existing service definition in place of the exec argument vector.启动给定的服务,并停止其他初始化命令的处理,直到返回为止。该命令的功能类似于exec 命令,但是使用现有的服务定义代替exec参数向量。
export <name> <value>
Set the environment variable name equal to value in the global environment (which will be inherited by all processes started after this command is executed)
将环境变量名称设置为等于全局环境中的值(将由执行此命令后启动的所有进程继承)
hostname <name>
Set the host name.
设置host name。
ifup <interface>
Bring the network interface interface online.
使网络接口接口联机。
insmod [-f] <path> [<options>]
Install the module at path with the specified options. -f: force installation of the module even if the version of the running kernel and the version of the kernel for which the module was compiled do not match.
使用指定的选件将模块安装在路径上。-f:即使正在运行的内核版本与为其编译模块的内核版本不匹配,也将强制安装模块。
interface_start <name>
interface_restart <name>
interface_stop <name>
Find the service that provides the interface name if it exists and run the
start
,restart
, orstop
commands on it respectively. name may be either a fully qualified HIDL name, in which case it is specified as<interface>/<instance>
, or an AIDL name, in which case it is specified asaidl/<interface>
for exampleandroid.hardware.secure_element@1.1::ISecureElement/eSE1
oraidl/aidl_lazy_test_1
.查找提供接口名称的服务(如果存在),然后分别在其上运行start ,restart 或stop 命令。name 可以是标准的HIDL名称(在这种情况下,其指定为<interface> / <instance>),或者可以是AIDL名称,在这种情况下,其指定为aidl / <interface> ,例如android.hardware.secure_element @ 1.1 :: ISecureElement / eSE1 或aidl / aidl_lazy_test_1 。
Note that these commands only act on interfaces specified by the
interface
service option, not on interfaces registered at runtime.请注意,这些命令仅对由interface service选项指定的接口起作用,而不对在运行时注册的接口起作用。
这些命令的示例用法:
Example usage of these commands:
interface_start android.hardware.secure_element@1.1::ISecureElement/eSE1
will start the HIDL Service that provides theandroid.hardware.secure_element@1.1
andeSI1
instance.interface_start aidl/aidl_lazy_test_1
will start the AIDL service that provides theaidl_lazy_test_1
interface.interface_start android.hardware.secure_element@1.1 :: ISecureElement / eSE1 将启动提供了android.hardware.secure_element@1.1 和eSI1 实例的HIDL服务。interface_start aidl / aidl_lazy_test_1 将启动提供aidl_lazy_test_1 接口的AIDL服务。
load_system_props
(This action is deprecated and no-op.)
(此操作已弃用,无操作。)
load_persist_props
Loads persistent properties when /data has been decrypted. This is included in the default init.rc.
/ data解密后,加载持久性属性。这包含在默认的init.rc中。
loglevel <level>
Sets init's log level to the integer level, from 7 (all logging) to 0 (fatal logging only). The numeric values correspond to the kernel log levels, but this command does not affect the kernel log level. Use the
write
command to write to/proc/sys/kernel/printk
to change that. Properties are expanded within level.将初始化的日志级别设置为整数级别,从7(所有日志记录)到0(仅致命日志记录)。数值对应于内核日志级别,但是此命令不影响内核日志级别。使用write 命令来写入/ proc / sys / kernel / printk 来更改它。属性在级别内扩展。
mark_post_data
Used to mark the point right after /data is mounted. Used to implement the
class_reset_post_data
andclass_start_post_data
commands.挂载/ data后用于标记该点。用于实现class_reset_post_data 和class_start_post_data 命令。
mkdir <path> [<mode>] [<owner>] [<group>] [encryption=<action>] [key=<key>]
Create a directory at path, optionally with the given mode, owner, and group. If not provided, the directory is created with permissions 755 and owned by the root user and root group. If provided, the mode, owner and group will be updated if the directory exists already.
在path上创建目录,可以选择使用给定的模式,所有者和组。如果未提供,则创建目录的权限为755,并由root用户和root组拥有。如果提供了该目录,则将更新模式,所有者和组。
action can be one of:
动作可以是以下之一:
None
:不执行任何加密操作;如果父目录被加密,则目录将被加密。Require
: 加密目录,如果加密失败,则中止引导过程Attempt
: 尝试设置加密策略,但如果失败,则继续DeleteIfNecessary
: 递归删除目录(如果需要)以设置加密策略。
key can be one of:
密钥可以是以下之一:
ref
: use the systemwide DE key 使用系统范围的DE键per_boot_ref
: use the key freshly generated on each boot. 使用每次引导时新生成的密钥。
mount_all <fstab> [ <path> ]\* [--<option>]
Calls fs_mgr_mount_all on the given fs_mgr-format fstab with optional options “early” and “late”. With “--early” set, the init executable will skip mounting entries with “latemount” flag and triggering fs encryption state event. With “--late” set, init executable will only mount entries with “latemount” flag. By default, no option is set, and mount_all will process all entries in the given fstab.
使用给定的fs_mgr格式fstab调用fs_mgr_mount_all,并带有可选选项“ early”和“ late”。设置为“ --early”后,init可执行文件将跳过带有“ latemount”标志的安装条目并触发fs加密状态事件。设置为“ --late”后,init可执行文件将仅装载带有“ latemount”标志的条目。默认情况下,未设置任何选项,并且mount_all将处理给定fstab中的所有条目。
mount <type> <device> <dir> [ <flag>\* ] [<options>]
Attempt to mount the named device at the directory dir _flag_s include “ro”, “rw”, “remount”, “noatime”, ... options include “barrier=1”, “noauto_da_alloc”, “discard”, ... as a comma separated string, e.g. barrier=1,noauto_da_alloc
尝试将命名设备挂载到目录dir _flag_s包括“ ro”,“ rw”,“ remount”,“ noatime”,... 选项包括“ barrier = 1”,“ noauto_da_alloc”,“ discard”,...作为逗号分隔的字符串,例如barrier = 1,noauto_da_alloc
parse_apex_configs
Parses config file(s) from the mounted APEXes. Intended to be used only once when apexd notifies the mount event by setting apexd.status to ready.
从已安装的APEX解析配置文件。旨在仅当apexd通过将apexd.status设置为ready通知安装事件时才使用一次。
restart <service>
Stops and restarts a running service, does nothing if the service is currently restarting, otherwise, it just starts the service.
停止并重新启动正在运行的服务,如果该服务当前正在重新启动,则不执行任何操作,否则,它将仅启动该服务。
restorecon <path> [ <path>\* ]
Restore the file named by path to the security context specified in the file_contexts configuration. Not required for directories created by the init.rc as these are automatically labeled correctly by init.
将按路径命名的文件还原到file_contexts配置中指定的安全上下文。由init.rc创建的目录不需要,因为这些目录会由init自动正确标记。
restorecon_recursive <path> [ <path>\* ]
Recursively restore the directory tree named by path to the security contexts specified in the file_contexts configuration.
递归地将由路径命名的目录树恢复到file_contexts配置中指定的安全上下文。
rm <path>
Calls unlink(2) on the given path. You might want to use “exec -- rm ...” instead (provided the system partition is already mounted).
在给定路径上调用unlink(2)。您可能想改用“ exec-rm ...”(前提是已经安装了系统分区)。
rmdir <path>
Calls rmdir(2) on the given path.
在给定路径上调用rmdir(2)。
readahead <file|dir> [--fully]
Calls readahead(2) on the file or files within given directory. Use option --fully to read the full file content.
在给定目录中的一个或多个文件上调用readahead(2)。使用选项-完全读取完整的文件内容。
setprop <name> <value>
Set system property name to value. Properties are expanded within value.
将系统属性名称设置为value 。属性在值内扩展。
setrlimit <resource> <cur> <max>
Set the rlimit for a resource. This applies to all processes launched after the limit is set. It is intended to be set early in init and applied globally. resource is best specified using its text representation (‘cpu’, ‘rtio’, etc or ‘RLIM_CPU’, ‘RLIM_RTIO’, etc). It also may be specified as the int value that the resource enum corresponds to. cur and max can be ‘unlimited’ or ‘-1’ to indicate an infinite rlimit.
设置资源的rlimit。这适用于在设置限制后启动的所有进程。它旨在尽早在init中设置并在全球范围内应用。资源是使用其文本表示(“CPU”,“RTIO”等或者“RLIM_CPU”,“RLIM_RTIO”等)最好指定。也可以将其指定为资源枚举对应的int值。cur 和max 可以是'unlimited'或'-1'来表示无限的rlimit。
start <service>
Start a service running if it is not already running. Note that this is not synchronous, and even if it were, there is no guarantee that the operating system‘s scheduler will execute the service sufficiently to guarantee anything about the service’s status. See the
exec_start
command for a synchronous version ofstart
.如果服务尚未运行,请启动它。请注意,这不是同步的,即使是同步的,也无法保证操作系统的调度程序将充分执行服务以保证有关服务状态的任何信息。见exec_start 为同步version命令启动。
This creates an important consequence that if the service offers functionality to other services, such as providing a communication channel, simply starting this service before those services is not sufficient to guarantee that the channel has been set up before those services ask for it. There must be a separate mechanism to make any such guarantees.
这将创建一个重要的后果是,如果该服务提供的功能的其他服务,如提供通信通道,只需启动这些服务之前,这项服务是不足够的,以保证这些服务前的通道已设置提出要求。必须有单独的机制来做出任何此类保证。
stop <service>
Stop a service from running if it is currently running.
如果服务当前正在运行,请停止该服务。
swapon_all <fstab>
Calls fs_mgr_swapon_all on the given fstab file.
在给定的fstab文件上调用fs_mgr_swapon_all。
symlink <target> <path>
Create a symbolic link at path with the value target
在具有目标值的路径上创建符号链接
sysclktz <minutes_west_of_gmt>
Set the system clock base (0 if system clock ticks in GMT)
设置系统时钟基准(如果系统时钟在GMT中计时,则为0)
trigger <event>
Trigger an event. Used to queue an action from another action.
触发事件。用于将另一个操作中的一个操作排队。
umount <path>
Unmount the filesystem mounted at that path.
卸载在该路径上挂载的文件系统。
verity_update_state <mount-point>
Internal implementation detail used to update dm-verity state and set the partition.mount-point.verified properties used by adb remount because fs_mgr can't set them directly itself.
内部实现细节,用于更新dm-verity状态和设置分区。由于fs_mgr本身无法直接设置它们,因此将重新安装adb使用的mount-point .verified属性。
wait <path> [ <timeout> ]
Poll for the existence of the given file and return when found, or the timeout has been reached. If timeout is not specified it currently defaults to five seconds.
轮询给定文件的存在性,并在找到文件或超时时返回。如果未指定超时,则当前默认为五秒钟。
wait_for_prop <name> <value>
Wait for system property name to be value. Properties are expanded within value. If property name is already set to value, continue immediately.
等待系统属性名称为value 。属性在值内扩展。如果属性名称已设置为value ,请立即继续。
write <path> <content>
Open the file at path and write a string to it with write(2). If the file does not exist, it will be created. If it does exist, it will be truncated. Properties are expanded within content.
在path 处打开文件,然后使用write(2)向其中写入一个字符串。如果文件不存在,将创建它。如果确实存在,它将被截断。属性在内容中扩展。
Imports
import <path>
解析一个初始化配置文件,扩展当前配置。如果path 是目录,则目录中的每个文件都将被解析为配置文件。它不是递归的,不会解析嵌套目录。
import关键字不是命令,而是它自己的部分,这意味着它不是作为Action的一部分发生的,而是在解析文件并遵循以下逻辑时处理导入。
初始化可执行文件只导入三次.rc文件:
- 在初始引导过程中导入/init.rc或由属性ro.boot.init_rc 指示的脚本时。
- 在导入/init.rc后立即为第一阶段安装设备导入/ {system,vendor,odm} / etc / init /时。
- (不建议使用)在mount_all期间在指定路径上导入/ {system,vendor,odm} / etc / init /或.rc文件时,不允许在Q之后启动设备。
出于传统原因,并且为了保持向后兼容性,导入文件的顺序有些复杂。不严格保证。
确保在执行不同命令之前已运行命令的唯一正确方法是:1)将其放置在具有较早执行的触发器的Action中,或2)将其放置在具有相同触发器的Action中,该触发器位于同一文件的同一文件中。较早的行。
但是,第一阶段安装设备的实际顺序为:
- 解析/init.rc,然后递归地解析其每个导入。
- / system / etc / init /的内容按字母顺序依次解析,并且在解析每个文件后以递归方式进行导入。
- 对/ vendor / etc / init重复步骤2,然后对/ odm / etc / init重复
下面的伪代码可以更清楚地解释这一点:
fn Import(file)
Parse(file)
for (import : file.imports)
Import(import)
Import(/init.rc)
Directories = [/system/etc/init, /vendor/etc/init, /odm/etc/init]
for (directory : Directories)
files = <Alphabetical order of directory's contents>
for (file : files)
Import(file)
Properties
Init提供具有以下属性的状态信息。
init.svc.<name>
命名服务的状态(“stopped”, “stopping”, “running”, “restarting”)
dev.mnt.blk.<mount_point>
Block device base name associated with a mount_point. The mount_point has / replaced by . and if referencing the root mount point “/”, it will use “/root”, specifically
dev.mnt.blk.root
. Meant for references to/sys/device/block/${dev.mnt.blk.<mount_point>}/
and/sys/fs/ext4/${dev.mnt.blk.<mount_point>}/
to tune the block device characteristics in a device agnostic manner.
初始化响应以ctl 开头的属性。。这些性质采取的格式ctl.[<target>_]<command>
和value的系统属性的被用作参数。该target是可选的,指定服务选项的value是为了配合。target 和interface 仅有一个选项,它指示value将引用服务提供的接口,而不是服务名称本身。
例如:
SetProperty("ctl.start", "logd")
will run the start
command on logd
.
SetProperty("ctl.interface_start", "aidl/aidl_lazy_test_1")
will run the start
command on the service that exposes the aidl aidl_lazy_test_1
interface.
注意,这些属性只能设置。它们在读取时将没有任何价值。
这些命令在下面列出。
start
restart
stop
这些等效于在属性值指定的服务上使用start ,restart 和stop 命令。
oneshot_one 和oneshot_off 将为该属性的值指定的服务打开或关闭oneshot 标志。这特别适用于有条件的惰性HAL。当它们是惰性HAL时,必须启用oneshot,否则应禁用oneshot。
sigstop_on 和sigstop_off 将为该属性的值指定的服务打开或关闭sigstop 功能。有关此功能的更多详细信息,请参见下面的调试初始化部分。
Boot timing
初始化在系统属性中记录一些引导时间信息。
ro.boottime.init
Time after boot in ns (via the CLOCK_BOOTTIME clock) at which the first stage of init started.
引导的第一阶段开始后的启动时间(以ns为单位)(通过CLOCK_BOOTTIME时钟)。
ro.boottime.init.first_stage
How long in ns it took to run first stage.
运行第一阶段所花的时间为ns。
ro.boottime.init.selinux
How long in ns it took to run SELinux stage.
运行SELinux阶段花费了ns的时间。
ro.boottime.init.cold_boot_wait
How long init waited for ueventd's coldboot phase to end.
init等待ueventd的Coldboot阶段结束的时间。
ro.boottime.<service-name>
Time after boot in ns (via the CLOCK_BOOTTIME clock) that the service was first started.
ns启动后的时间(通过CLOCK_BOOTTIME时钟),该服务首次启动。
Bootcharting
此版本的init包含执行“引导图”的代码:生成日志文件,这些文件随后可以由http://www.bootchart.org/提供的工具进行处理。
在模拟器上,使用-bootchart timeout 选项启动,并在超时秒数内激活bootcharting 。
在设备上:
adb shell 'touch /data/bootchart/enabled'
收集完数据后,不要忘记删除此文件!
日志文件被写入/ data / bootchart /。提供了一个脚本来检索它们并创建可以与bootchart命令行实用程序一起使用的bootchart.tgz文件:
sudo apt-get install pybootchartgui
# grab-bootchart.sh uses $ANDROID_SERIAL.
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh
要注意的一件事是,启动图将显示init好像它从0s开始运行。您必须查看dmesg才能确定内核实际启动init的时间。
Comparing two bootcharts
一个名为compare-bootcharts.py的方便脚本可用于比较选定进程的开始/结束时间。前面提到的grab-bootchart.sh将在/ tmp / android-bootchart保留一个名为bootchart.tgz的引导图压缩包。如果两个这样的tarball保留在主机上不同目录下,则脚本可以列出时间戳差异。例如:
Usage: system/core/init/compare-bootcharts.py base-bootchart-dir exp-bootchart-dir
process: baseline experiment (delta) - Unit is ms (a jiffy is 10 ms on the system)
------------------------------------
/init: 50 40 (-10)
/system/bin/surfaceflinger: 4320 4470 (+150)
/system/bin/bootanimation: 6980 6990 (+10)
zygote64: 10410 10640 (+230)
zygote: 10410 10640 (+230)
system_server: 15350 15150 (-200)
bootanimation ends at: 33790 31230 (-2560)
Systrace
Systrace(http://developer.android.com/tools/help/systrace.html)可用于在userdebug或eng构建的启动期间获取性能分析报告。
这是“ wm”和“ am”类别的跟踪事件的示例:
$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py \
wm am --boot
该命令将导致设备重启。重新启动设备并完成启动顺序后,通过单击Ctrl + C,可以从设备获取跟踪报告并将其写为trace.html在主机上。
限制:记录跟踪事件是在加载持久属性后开始的,因此之前记录的跟踪事件不会被记录。诸如vold,surfaceflinger和servicemanager之类的一些服务受此限制的影响,因为它们是在加载持久属性之前启动的。Zygote初始化和从合子派生的过程不受影响。
Debugging init
当服务从init启动时,它可能无法使该服务执行execv()。这不是典型的情况,并且可能指示在启动新服务时链接器中发生错误。Android中的链接器将其日志打印到logd 和stderr ,因此它们在logcat 中可见。如果遇到错误之前,可以访问的logcat ,在stdio_to_kmsg 服务选项可用于指导日志的链接打印到标准错误到kmsg ,在那里他们可以通过串行端口读取。
不建议在不使用init的情况下启动init服务,因为init会设置大量难以手动复制的环境(用户,组,安全标签,功能等)。
如果需要从一开始就调试服务,则添加sigstop 服务选项。此选项将在调用exec之前立即将SIGSTOP发送到服务。这提供了一个窗口,在此窗口中,开发人员可以在继续使用SIGCONT进行服务之前附加调试器,strace等。
也可以通过ctl.sigstop_on和ctl.sigstop_off属性动态控制此标志。
以下是通过上述内容动态调试日志的示例:
stop logd
setprop ctl.sigstop_on logd
start logd
ps -e | grep logd
> logd 4343 1 18156 1684 do_signal_stop 538280 T init
gdbclient.py -p 4343
b main
c
c
c
> Breakpoint 1, main (argc=1, argv=0x7ff8c9a488) at system/core/logd/main.cpp:427
以下是使用strace进行相同操作的示例
stop logd
setprop ctl.sigstop_on logd
start logd
ps -e | grep logd
> logd 4343 1 18156 1684 do_signal_stop 538280 T init
strace -p 4343
(From a different shell)
kill -SIGCONT 4343
> strace runs
主机初始化脚本验证
在构建期间检查初始化脚本的正确性。具体而言,检查以下内容。
- 格式正确的动作,服务和导入部分,例如,没有前面的“在线”行就没有动作,并且在“导入”语句之后没有多余的行。
- 所有命令都映射到有效的关键字,并且参数计数在正确的范围内。
- 所有服务选项均有效。这比完全解析服务选项的参数时检查命令的方式严格,例如,必须解析UID和GID。
初始化脚本的其他部分仅在运行时进行解析,因此在构建时不会进行检查,其中包括以下内容。
- 命令参数的有效性,例如,不检查文件路径是否确实存在,SELinux是否允许该操作或UID和GID是否解析。
- 不检查服务是否存在或定义了有效的SELinux域
- 不检查服务是否以前未在其他初始化脚本中定义。
早期init引导顺序
早期的init引导序列分为三个阶段:第一阶段init,SELinux设置和第二阶段init。
第一阶段init负责设置最低的最低要求,以加载系统的其余部分。具体来说,这包括挂载/ dev,/ proc,挂载“早期挂载”分区(该分区需要包含所有包含系统代码的分区,例如系统和供应商),并将system.img挂载移动到具有虚拟磁盘的设备上。
请注意,在Android Q中,system.img始终包含TARGET_ROOT_OUT,并且始终在第一阶段初始化完成时在/挂载。Android Q也将需要动态分区,因此将需要使用ramdisk来启动Android。恢复ramdisk可以用于引导至Android,而不是专用的ramdisk。
根据设备配置,第一阶段的init有三个变体:
- 对于以系统为根的设备,第一阶段初始化是/ system / bin / init的一部分,/ init处的符号链接指向/ system / bin / init,以实现向后兼容。这些设备不需要执行任何操作来挂载system.img,因为按照定义,它已经由内核作为rootfs挂载。
- 对于具有虚拟磁盘的设备,第一阶段的初始化是位于/ init的静态可执行文件。这些设备将system.img挂载为/ system,然后执行切换根操作以将/ system的挂载移动到/。安装完成后,将释放虚拟磁盘的内容。
- 对于将Recovery用作ramdisk的设备,其第一阶段初始化包含在恢复ramdisk中位于/ init的共享init中。这些设备首先将root切换到/ first_stage_ramdisk以从环境中删除恢复组件,然后执行与2)相同的操作。请注意,如果内核命令行中存在androidboot.force_normal_boot = 1,则决定是正常启动到Android而不是启动到恢复模式。
第一步初始化完成后,将使用“ selinux_setup”参数执行/ system / bin / init。在此阶段,可以选择将SELinux编译并加载到系统上。selinux.cpp包含有关此过程详细信息的更多信息。
最后,该阶段完成后,将使用“ second_stage”参数再次执行/ system / bin / init。此时,init的主要阶段将运行,并通过init.rc脚本继续引导过程。
原文地址:https://android.googlesource.com/platform/system/core/+/master/init/README.md