【Android】一文总结Android的init语言

🔺导读:

  • 1、在Android系统中,存在多个以xxx.rc形式命名的文件,这些文件可以理解成Android系统配置文件,在Android系统启动过程中,由init进程加载并解析,这些文件中的内容形成了Android的init语言,是语言就存在一定的语法、格式、命令和参数等。

  • 2、为了在阅读这些rc文件时不至于茫然无措,也为了更加深入的理解Android系统的启动过程,也为了后续能够深度的定制Android系统,总结了在rc文件中常使用的command、option等,便于备查理解!

  • 3、本文来源于Android 11源码,几乎总结了其中的所有内容,Android高版本或者低版本中是否存在更多的内容或者有些内容不存在,这是一个疑问!

文章目录


👉参考链接:http://aospxref.com/android-11.0.0_r21/xref/system/core/init/

一、Android init语言基础

Android init语言由五大类语句组成:Actions、Commands、Services、OptionsImports,上述这些都是面向行的,由空格分隔的令牌组成,C样式的反斜杠转义可用于在指令中插入空白,双引号可用来防止空白将文本分割成多个标记,当反斜杠是一行的最后一个字符时,可用于行折叠。

  • (1)以#开头的行(允许前导空格)表示注释。

  • (2)系统属性可以使用${property.name}语法展开,这也适用于需要连接的上下文中,例如import /init.recovery.${ro.hardware}.rc

  • (3)ActionsServices隐式声明了一个section,所有命令或选项都属于最近声明的section,忽略第一section之前的命令或选项。

  • (4)服务必须具有唯一的名称。如果使用与现有服务相同的名称定义第二个服务,该服务将被忽略并记录错误消息。

init语言在以.rc文件为扩展名的纯文本文件中描述,在Android系统中的多个地方通常存在多个这样的文件,/init.rc是第一个.rc文件,由init可执行文件在系统执行开始时加载,负责系统的初始设置。init会在加载/init.rc后立即加载/{system,,system_ext,vendor,odm,product}/etc/init/目录中包含的所有文件。这些目录的作用是:

  • /system/etc/init:用于核心系统项,例如SurfaceFlinger、MediaServicelogd
  • /vendor/etc/init/:用于SoC供应商项目,例如核心SoC功能所需的操作或守护进程。
  • /odm/etc/init/:用于设备制造商项目,例如运动传感器或其他外围功能所需的动作或守护进程。

没有第一阶段挂载机制的旧设备以前能够在mount_all期间导入init脚本,但是这已被弃用,并且不允许在Android Q之后的设备中使用。

所有服务的二进制文件驻留在system分区、vendor分区或odm分区上,它们的服务条目都应该放在相应的init.rc文件中,该文件位于它们所在分区的/etc/init/目录中。有一个构建系统宏LOCAL_INIT_RCLOCAL_INIT_RC用于将服务相关的rc文件编译到相应位置,每个init.rc文件还应该包含与其服务相关的操作。

根据init.rc文件的守护进程拆分init.rc文件比以前使用的整体init.rc文件更合理。原因如下:

  • (1)因为这种方法确保init读取的唯一服务条目和init执行的唯一操作对应于其二进制文件实际上存在于文件系统中的服务,而单个整体的init.rc文件则不是这种情况。
  • (2)当多个服务被添加到系统中时,拆分init.rc将便于解决合并冲突,因为每个服务都将进入一个单独的文件。

二、Action

动作是命名的命令序列。动作有一个触发器,用于确定动作何时执行。当发生与动作触发器匹配的事件时,该动作将被添加到待执行队列的尾部(除非它已经在队列上)。队列中的每个操作按顺序退出队列,该操作中的每个命令按顺序执行。init处理其他活动(设备创建/销毁、属性设置、进程重启)中命令的执行。

Action采用以下的语法格式:

on <trigger> [&& <trigger>]*
   <command>
   <command>
   <command>

操作将被添加到队列中,并根据包含它们的文件解析顺序执行,接着在单个文件中按顺序执行。例如一个文件包含如下action语句:

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

boot触发事件发生时,假设属性true等于true,则命令的执行顺序为:

setprop a 1
setprop b 2
setprop c 1
setprop d 2
setprop e 1
setprop f 2

(2-1)触发器

触发器是用于匹配特定类型事件并触发操作的字符串。触发器分为 事件触发器 和 属性触发器 。

事件触发器是由’trigger’ 命令或 init可执行文件中的QueueEventTrigger()函数触发的字符串。它们采用简单的字符串形式,如’boot’或 ‘late-init’。Android系统中常见的触发器如下所示:

  1. boot:系统引导时触发。
  2. early-init:早期初始化时触发,早于所有其他初始化步骤。
  3. init:在 init 进程启动后触发。
  4. late-init:在所有其他初始化步骤完成后触发,但在启动第一个 Service 之前。
  5. post-fs:在文件系统挂载后触发。
  6. post-fs-data:在 /data 分区挂载后触发。
  7. post-early-init:在早期初始化步骤之后但 init 进程启动之前触发。
  8. vendor-boot:在 vendor 分区引导时触发。
  9. vendor-early-init:在 vendor 分区早期初始化时触发。
  10. vendor-init:在 vendor 分区上 init 进程启动后触发。
  11. vendor-late-init:在 vendor 分区上所有其他初始化步骤完成后触发,但在启动第一个 Service 之前。
  12. verity-logging:在 Android Verified Boot 启用时触发。

属性触发器是在命名属性更改值为给定新值或命名属性更改值为任何新值时触发的字符串。它们采用 ‘property:=’ 和 ‘property:=*’ 的形式。在init的初始引导阶段期间,属性触发器会被额外评估和触发。

注意:一个操作可以有多个 属性触发器,但只能有一个 事件触发器。

例如:on boot && property:a=b定义了一个只有在’boot’事件触发并且属性a等于b时才执行的操作。

on property:a=b && property:c=d定义了一个在以下三种情况下执行的操作:

  • 1、在初始引导期间,如果属性 a=b 并且属性 c=d。
  • 2、在属性 a 过渡到值 b 时,同时属性 c 已经等于 d。
  • 3、在属性 c 过渡到值 d 时,同时属性 a 已经等于 b。

(2-2)Command总结

1、bootchart [start|stop]

启动/停止启动图记录。这些命令存在于默认的 init.rc 文件中,但仅当文件 /data/bootchart/enabled 存在时,启动图记录才会激活;否则,bootchart start/stop 将不起作用。

2、chmod <octal-mode> <path>

更改文件访问权限。

3、chown <owner> <group> <path>

更改文件所有者和组。

4、class_start <serviceclass>

如果尚未运行,则启动指定类的所有服务。有关启动服务的更多信息,参见 start 条目。

5、class_start_post_data <serviceclass>

类似于 class_start,但仅考虑在挂载 /data 后启动的服务,并且在调用 class_reset_post_data 时正在运行,仅用于 FDE 设备。

6、class_stop <serviceclass>

如果当前正在运行,则停止并禁用指定类的所有服务。

7、class_reset <serviceclass>

如果当前正在运行,则停止指定类的所有服务,但不会禁用它们,后续可以使用 class_start 重新启动它们。

8、class_reset_post_data <serviceclass>

类似于 class_reset,但仅考虑在挂载 /data 后启动的服务。仅用于 FDE 设备。

9、class_restart <serviceclass>

重新启动指定类的所有服务。

10、copy <src> <dst>

复制文件。类似于 write,对于二进制/大量数据很有用。不允许从符号链接文件和可全局写入或可组写入文件复制。对于 dst 文件,默认创建模式为 0600(如果不存在)。如果 dst 文件是普通常规文件并且已经存在,则将其截断。

11、domainname <name>

设置域名。

12、enable <servicename>

将禁用的服务转换为启用的服务。如果服务应该运行,则现在将启动它。通常在引导加载程序设置指示在需要时启动特定服务的变量时使用。例如:

on property:ro.boot.myfancyhardware=1
    enable my_fancy_service_for_my_fancy_hardware
13、exec [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]

fork()并执行带有给定参数的命令。命令在“–”之后,以便可以提供可选的安全上下文、用户和附加组。在此命令完成之前,不会运行其他命令。seclabel可以是 -,表示默认值。属性在参数中展开。init 在fork()的进程退出之前停止执行命令。

14、exec_background [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]

fork()并执行带有给定参数的命令。这与 exec 命令类似。不同之处在于,init 不会等待进程退出,而是继续执行后续命令。

15、exec_start <service>

启动给定的服务,并暂停执行其他 init 命令,直到它返回。该命令的功能类似于 exec 命令,但使用现有的服务定义替换 exec 参数向量。

16、export <name> <value>

在全局环境中将环境变量 name 设置为 value。

17、hostname <name>

设置主机名。

18、ifup <interface>

启动网络接口 interface

19、insmod [-f] <path> [<options>]

使用指定options在 path 处安装模块。-f:强制安装模块,即使运行内核的版本与编译模块的内核版本不匹配。

20、interface_start <name> \ interface_restart <name> \ interface_stop <name>

如果存在提供接口名称的服务,则分别在其上运行 start、restart 或 stop 命令。名称可以是合格的 HIDL 名称(在这种情况下,它被指定为 /),也可以是 AIDL 名称(在这种情况下,它被指定为 aidl/,例如 android.hardware.secure_element@1.1::ISecureElement/eSE1 或 aidl/aidl_lazy_test_1)。注意,这些命令仅对由 interface 服务选项指定的接口起作用,而不对运行时注册的接口起作用。例如:

//将启动提供 android.hardware.secure_element@1.1 和 eSI1 实例的 HIDL 服务。
interface_start android.hardware.secure_element@1.1::ISecureElement/eSE1 
    
//将启动提供 aidl_lazy_test_1 接口的 AIDL 服务。
interface_start aidl/aidl_lazy_test_1 
21、load_system_props

load_system_propsAction已被废弃!

22、load_persist_props

在 /data 已解密时加载持久存在的属性,这包含在默认的 init.rc 中。

23、loglevel <level>

此命令将 init 的日志级别设置为整数级别,范围从 7(所有日志)到 0(仅致命日志)。数字值对应于内核日志级别,但此命令不影响内核日志级别。可以在级别内扩展属性。

24、mark_post_data

用于标记 /data 挂载后的点,用于实现 class_reset_post_data 和 class_start_post_data 命令。

25、mkdir <path> [<mode>] [<owner>] [<group>] [encryption=<action>] [key=<key>]

在 path 处创建一个目录,可选择使用给定的模式、所有者和组。如果未提供,则该目录将以权限 755 创建,并由 root 用户和 root 组拥有。如果提供了模式、所有者和组,则如果目录已存在,将更新它们。


action可以是以下参数之一:

  • None:不采取加密措施。
  • Require:加密目录,如果加密失败,中止引导进程。
  • Attempt:尝试设置加密策略,但如果失败则继续。
  • DeleteIfNecessary:如果需要设置加密策略,递归删除目录。

key可以是以下参数之一:

  • ref:使用系统范围的DE密钥。
  • per_boot_ref:使用每次引导时新生成的密钥。

26、mount_all [ <fstab> ] [--<option>]

该命令调用 fs_mgr_mount_all 函数来挂载给定的 fs_mgr 格式的 fstab,可选择使用选项 “early” 和 “late”。当设置了 “–early” 选项时,init 可执行文件将跳过带有 “latemount” 标志的条目的挂载,并触发文件系统加密状态事件。当设置了 “–late” 选项时,init 可执行文件将仅挂载带有 “latemount” 标志的条目。默认情况下,不设置任何选项,mount_all 将处理给定 fstab 中的所有条目。如果未指定 fstab 参数,则会在运行时在 /odm/etc、/vendor/etc 或 / 下扫描 fstab. r o . b o o t . f s t a b s u f f i x 、 f s t a b . {ro.boot.fstab_suffix}、fstab. ro.boot.fstabsuffixfstab.{ro.hardware} 或 fstab.${ro.hardware.platform}。

27、mount <type> <device> <dir> [ <flag>\* ] [<options>]

尝试在目录 dir 处挂载指定设备。flag包括 “ro”、“rw”、“remount”、“noatime” 等。options包括 “barrier=1”、“noauto_da_alloc”、“discard” 等,以逗号分隔的字符串,例如 barrier=1,noauto_da_alloc。

28、parse_apex_configs

解析挂载的 APEXes 的配置文件,仅打算在 apexd 通过将 apexd.status 设置为 ready 通知挂载事件时使用一次。

29、restart <service>

停止并重新启动正在运行的服务;如果服务当前正在重新启动,则不执行任何操作,否则,只启动服务。

30、restorecon <path> [ <path>\* ]

path指定的文件恢复到file_contexts 配置中指定的安全上下文。对于由 init.rc 创建的目录,不需要此操作,因为 init 会自动正确标记它们。

31、restorecon_recursive <path> [ <path>\* ]

递归地将由path指定的目录树恢复到file_contexts配置中指定的安全上下文。

32、rm <path>

在给定路径上调用 unlink(2)。我们可能想要使用 “exec – rm …” 替代(前提是系统分区已挂载)。

33、rmdir <path>

在给定路径上调用 rmdir(2)。

34、readahead <file|dir> [--fully]

对文件或给定目录中的文件调用 readahead(2)。使用选项--fully 来读取完整的文件内容。

35、setprop <name> <value>

将系统属性 name 设置为 value,属性在值中展开。

36、setrlimit <resource> <cur> <max>

设置资源的 rlimit,这适用于在设置限制后启动的所有进程。它旨在早期设置 init 并全局应用。最佳方式是使用其文本表示(‘cpu’、‘rtio’ 等或 ‘RLIMCPU’、‘RLIMRTIO’ 等)。cur 和 max 可以是 ‘unlimited’ 或 ‘-1’,表示无限制的 rlimit。

37、start <service>

如果尚未运行,则启动服务。注意,该命令不是同步的,并且即使是同步的,也不能保证操作系统的调度器会执行足够的服务以保证服务的正确状态。如果服务向其他服务提供功能,例如提供通信通道,则仅启动此服务以启动这些服务是不足以保证通道已设置完成,因此必须有一个单独的机制来做出这种保证。

38、stop <service>

如果当前正在运行,则停止服务。

39、swapon_all [ <fstab> ]

对给定的 fstab 文件调用 fs_mgr_swapon_all,如果未指定 fstab 参数,则在运行时会在 /odm/etc、/vendor/etc/ 下扫描 fstab.${ro.boot.fstab_suffix}、fstab.${ro.hardware}fstab.${ro.hardware.platform}

40、symlink <target> <path>

在 path 处创建一个符号链接,其值为 target。

41、sysclktz <minutes_west_of_gmt>

设置系统时钟基准(如果系统时钟以 GMT 计时,则为 0)。

42、trigger <event>

该命令用于触发事件,用于从另一个动作队列中的动作。

43、umount <path>

卸载在该path上挂载的文件系统。

44、umount_all [ <fstab> ]

对给定的 fstab 文件调用 fs_mgr_umount_all。如果未指定 fstab 参数,则在运行时会在 /odm/etc、/vendor/etc 或 / 下扫描 fstab. r o . b o o t . f s t a b s u f f i x 、 f s t a b . {ro.boot.fstab_suffix}、fstab. ro.boot.fstabsuffixfstab.{ro.hardware} 或 fstab.${ro.hardware.platform}。

45、verity_update_state <mount-point>

用于更新 dm-verity 状态和设置 adb remount 使用的 partition.mount-point.verified 属性的内部实现细节,因为 fs_mgr 无法直接设置它们。

46、wait <path> [ <timeout> ]

等待给定文件的存在,并在找到或超时时返回。如果未指定timeout,则当前默认为五秒。超时值可以是浮点数秒,以浮点表示法指定。

47、wait_for_prop <name> <value>

等待系统属性 name 的值为 value,属性在值中展开,如果属性 name 已设置为 value,则立即继续执行。

48、write <path> <content>

打开path处的文件,并使用 write(2) 向其写入字符串,如果文件不存在,则将创建它,如果存在,则将截断它。属性在内容中展开。

三、Service

服务是初始化启动并(可选地)退出时重新启动的程序。服务的形式有:

service <name> <pathname> [ <argument> ]*
   <option>
   <option>
   ...

(3-1)Options总结

option是服务的修饰符,它们影响init运行服务的方式和时间。有如下的Options:

1、capabilities [ \* ]

设置此服务在执行时的能力。‘capability’ 应该是一个 Linux 能力,不包含 “CAP_” 前缀,如 “NET_ADMIN” 或 “SETPCAP”。参见 Linux 能力列表 获取所有 Linux 能力。如果没有提供能力,则从此服务中删除所有能力,即使它以 root 用户身份运行也是如此。

2、class [ \* ]

为服务指定类名。具有相同类名的所有服务可以一起启动或停止。如果未通过 class 选项指定类,则所有服务都属于类 “default”。除了(必需的)第一个类名之外的其他类名用于分组服务。动画类应包括所有启动动画和关闭动画所需的服务。由于这些服务可以在启动期间非常早期启动,并且可以在关闭的最后阶段运行,因此不能保证对 /data 分区的访问。这些服务可以检查 /data 下的文件,但不应保持文件打开状态,并且在 /data 不可用时应当正常工作。

3、console [<console>]

此服务需要一个控制台。可选的第二个参数选择一个特定的控制台,而不是默认的。默认的 “/dev/console” 可以通过设置 “androidboot.console” 内核参数来更改。在所有情况下,前导的 “/dev/” 应省略,因此 “/dev/tty0” 应该被指定为 “console tty0”。此选项将 stdin、stdout 和 stderr 连接到控制台。它与 stdiotokmsg 选项互斥,后者仅将 stdout 和 stderr 连接到 kmsg。

4、critical

表示这是一个设备关键的服务。如果它在四分钟内退出超过四次,或在引导完成之前退出,则设备将重新启动到引导加载程序。

5、disabled

此服务不会自动随其类别启动。必须通过名称或接口名称显式启动它。

6、enter_namespace <type> <path>

进入位于指定路径下的指定类型的命名空间。目前仅支持类型为 “net” 的网络命名空间。请注意,只能进入给定类型的一个命名空间。

7、file <path> <type>

打开指定path的文件,并将其文件描述符传递给启动的进程。类型必须为 “r”、“w” 或 “rw”。对于原生可执行文件,可参见 libcutils android_get_control_file()。

8、group <groupname> [ <groupname>\* ]

在执行此服务之前切换到指定的组。除了(必需的)第一个组名之外的其他组名用于设置进程的附加组(通过 setgroups() 实现)。当前默认为 root。(??? 可能应该默认为 nobody)

9、interface <interface name> <instance name>

将此服务与其提供的一组 HIDL 服务关联起来。接口名称必须是完全合格的名称,而不是值名称。例如,这用于允许 hwservicemanager 惰性启动服务。当提供多个接口时,应该多次使用此标签。例如:interface vendor.foo.bar@1.0::IBaz default

10、ioprio <class> <priority>

通过 SYSioprioset 系统调用设置此服务的 IO 优先级和 IO 优先级类别。类别必须是 “rt”、“be” 或 “idle” 中的一种。优先级必须是介于 0 到 7 之间的整数。

11、keycodes <keycode> [ <keycode>\* ]

设置触发此服务的keycodes。如果按下与传递的按键代码相对应的所有按键,则服务将启动。这通常用于启动 bugreport 服务。此选项可以接受属性,而不是按键代码列表。在这种情况下,只提供一个选项:典型属性扩展格式中的属性名称,该属性必须包含一个逗号分隔的按键代码值列表,或者文本 ‘none’,表示此服务不响应按键代码。

12、memcg.limit_in_bytes <value>和memcg.limit_percent <value>

将子进程的 memory.limitinbytes 设置为 limit_in_bytes 字节和 limit_percent 的最小值,后者被解释为设备物理内存大小的百分比(仅在 memcg 挂载时有效)。值必须大于或等于 0。

13、memcg.limit_property <value>

将子进程的 memory.limitinbytes 设置为指定属性的值(仅在 memcg 挂载时有效)。该属性将覆盖通过 memcg.limit_in_bytes 和 memcg.limit_percent 指定的值。

14、memcg.soft_limit_in_bytes <value>

将子进程的 memory.softlimitin_bytes 设置为指定值(仅在 memcg 挂载时有效),该值必须大于或等于 0。

15、memcg.swappiness <value>

将子进程的 memory.swappiness 设置为指定值(仅在 memcg 挂载时有效),该值必须大于或等于 0。

16、namespace <pid|mnt>

在fork服务时进入新的 PID 或挂载命名空间。

17、oneshot

表示服务退出时不重新启动。

18、onrestart

表示服务重新启动时执行一个命令。

19、oom_score_adjust <value>

将子进程的 /proc/self/oom_score_adj 设置为指定值,该值必须介于 -1000 到 1000 之间。

20、override

指示此服务定义旨在覆盖先前对同名服务的定义。这通常用于在 /odm 上覆盖在 /vendor 上定义的服务。init 解析的最后一个带有此关键字的服务定义将用于此服务。注意 init.rc 文件的解析顺序,因为它向后兼容性,所以具有一些特殊性。

21、priority <priority>

表示服务进程的调度优先级。此值必须在 -20 到 19 的范围内。默认优先级为 0。优先级通过 setpriority() 设置。

22、reboot_on_failure <target>

如果此进程无法启动,或者进程以除 CLD_EXITED 外的退出码或除 ‘0’ 外的状态终止,则使用指定的目标重新启动系统。target 的格式与 sys.powerctl 参数相同。这特别用于执行启动时必须进行的任何关键检查的 exec_start 内置。

24、restart_period <seconds>

如果非一次性服务退出,则将其重新启动时间加上此时段。默认为 5 秒,以限制崩溃服务的速率。对于定期运行的服务,可以增加此时段。例如,可以将其设置为 3600,表示该服务应每小时运行一次,或者设置为 86400,表示该服务应每天运行一次。

25、rlimit <resource> <cur> <max>

将给定的 rlimit 应用于服务,子进程会继承 rlimit,因此这实际上将给定的 rlimit 应用于此服务启动的进程树。其解析方式与下面指定的 setrlimit 命令类似。

26、seclabel <seclabel>

在执行此服务之前切换到指定的安全标签,主要用于从 rootfs 运行的服务,例如 ueventd、adbd。系统分区上的服务可以使用基于其文件安全上下文的策略定义的转换。如果未指定并且策略中未定义转换,则默认为 init 上下文。

27、setenv <name> <value>

在启动的进程中将环境变量 name 设置为 value。

28、shutdown <shutdown_behavior>

设置服务进程的关闭行为,如果未指定,则在关闭过程中使用 SIGTERM 和 SIGKILL 杀死服务。shutdown_behavior 为 “critical” 的服务在关闭时不会被杀死,直到关闭超时。当关闭超时时,即使标记为 “shutdown critical” 的服务也将被杀死。当标记为 “shutdown critical” 的服务在关闭开始时未运行时,它将被启动。

29、sigstop

在调用 exec 之前立即向服务发送 SIGSTOP,常用于调试。

30、socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]

创建名为 /dev/socket/name 的 UNIX 域套接字,并将其文件描述符传递给启动的进程,类型必须是 “dgram”、“stream” 或 “seqpacket”。类型可以以 “+passcred” 结尾,以在套接字上启用SO_PASSCRED,用户和组默认为 0。‘seclabel’ 是套接字的 SELinux 安全上下文。它默认为服务安全上下文,如 seclabel 指定的或根据服务可执行文件的安全上下文计算的。

31、stdio_to_kmsg

stdoutstderr 重定向到 /dev/kmsgdebug,这对于在早期启动期间不使用本地 Android 日志记录且我们希望捕获其日志消息的服务非常有用。仅在启用 /dev/kmsgdebug 时才启用此选项,该选项仅在 userdebug 和 eng 构建上启用。这与 console 选项互斥,后者还将 stdin 连接到给定的控制台。

32、task_profiles <profile> [ <profile>\* ]

在进程fork时为进程设置任务配置文件,这旨在替代 writepid 选项,用于将进程移到 cgroup 中。

33、timeout_period <seconds>

在此时段后,服务将被终止,此处尊重 oneshot 关键字,因此一次性服务不会自动重新启动,但所有其他服务都会。这对于创建与上面描述的 restart_period 选项结合使用的定期服务特别有用。

34、updatable

标记该服务可以在引导序列的后续阶段由 APEXes 覆盖(通过 ‘override’ 选项),如果带有 updatable 选项的服务在所有 APEXes 激活之前启动,则执行将延迟直到激活完成。未标记为 updatable 的服务无法被 APEXes 覆盖。

35、user <username>

在执行此服务之前切换到指定的用户名。目前默认为 root。(??? 可能应该默认为 nobody)从 Android M 开始,即使进程需要 Linux 能力,也应该使用此选项。以前,要获取 Linux 能力,进程需要以 root 身份运行,请求能力,然后降至所需的 uid。通过 fs_config,现在可以让设备制造商将 Linux 能力添加到应该使用的特定文件系统上的特定二进制文件中。有关此新机制的说明,请参阅 http://source.android.com/devices/tech/config/filesystem.html。使用此新机制时,进程可以使用 user 选项选择其所需的 uid,而无需以 root 身份运行。从 Android O 开始,进程还可以直接在其 .rc 文件中请求capabilities。

36、writepid <file> [ <file>\* ]

在fork时将子进程的 pid 写入给定的文件,用于 cgroup/cpuset 使用,如果未指定 /dev/cpuset/ 下的文件,但系统属性 ‘ro.cpuset.default’ 设置为非空 cpuset 名称(例如 ‘/foreground’),则将 pid 写入文件 /dev/cpuset/cpuset_name/tasks。此选项用于将进程移入 cgroup 的用途已经过时。请改用 task_profiles 选项。

四、Imports解析

Imports有如下的形式:

import <path>

解析init配置文件,扩展当前配置。如果path是一个目录,目录中的每个文件都被解析为一个配置文件。但是它不是递归的,所以嵌套目录不会被解析。import关键字不是命令,而是它自己的section,这意味着它不是作为Action的一部分发生,而是作为正在解析的文件处理导入,并遵循以下逻辑。

init可执行文件只有三次导入.rc文件:

  • 1、当init导入/init.rc或在初始引导时属性ro.boot.init_rc所指示的脚本。

  • 2、当它在导入/init.rc后立即为第一阶段挂载设备导入/{system,vendor,odm}/etc/init/时。

  • 3、步骤2重复/vendor/etc/init,然后/odm/etc/init

确保某个命令在另一个命令之前运行的唯一正确方法是:1)将它放在具有较早执行的触发器的动作中,或者 2)将它放在相同文件中相同触发器的动作中,但在较早的行中。

尽管如此,在第一阶段挂载设备的情况下,通常的顺序是:

  • 1、解析/init.rc,然后递归解析它的每个导入。
  • 2、对/system/etc/init/的内容进行按字母顺序排序,并按顺序解析,每个文件解析后递归进行导入。
  • 3、对/vendor/etc/init//odm/etc/init/重复步骤2。

五、启动时间

init在系统属性中记录了一些启动时间信息。

  • ro.boottime.init:使用CLOCK_BOOTTIME时钟(以纳秒为单位)启动 init 的第一阶段后的时间。

  • ro.boottime.init.first_stage:运行第一阶段所花费的时间(以纳秒为单位)。

  • ro.boottime.init.selinux:运行SELinux阶段所花费的时间(以纳秒为单位)。

  • ro.boottime.init.cold_boot_wait:init等待ueventd冷启动阶段结束的时间(以纳秒为单位)。

  • ro.boottime.:服务首次启动后的时间(以纳秒为单位),使用 CLOCK_BOOTTIME 时钟。

相关推荐

  1. Android总结Androidinit语言

    2024-04-08 08:30:04       13 阅读
  2. android系列-init SetupSelinux

    2024-04-08 08:30:04       39 阅读
  3. Android init.rc 解析

    2024-04-08 08:30:04       21 阅读
  4. Android 11 init进程对Selinux处理

    2024-04-08 08:30:04       16 阅读
  5. android系列-init 初始化日志

    2024-04-08 08:30:04       34 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-08 08:30:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-08 08:30:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-08 08:30:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-08 08:30:04       20 阅读

热门阅读

  1. QWebApp http服务器笔记

    2024-04-08 08:30:04       12 阅读
  2. HashMap底层源码面试题

    2024-04-08 08:30:04       14 阅读
  3. 升级到springdoc的Swagger3

    2024-04-08 08:30:04       13 阅读
  4. 2024.4.7力扣刷题记录-数组篇刷题记录2

    2024-04-08 08:30:04       14 阅读
  5. 蓝桥杯常用模板

    2024-04-08 08:30:04       13 阅读
  6. 设计模式:生活中的迭代器模式

    2024-04-08 08:30:04       14 阅读