Anroid init.rc基本知识

init.rc是用Android Init Language编写的后缀名为rc的纯文本文件,Android Init Language的语法在aosp源码/system/core/init/readme.md中有讲解,本文也是基于readme.md写的。

Android Init Language语法中有5个关键字: Actions(动作), Commands(命令), Services(服务), Options(选项), and Imports(引用).
基本语法规则:
1.每一行表示一条语句,行尾带反斜杠的话表示下一行是同行
2.关键字和参数之间用空格隔开,如果参数本身含有空格的话则需要用反斜杠转义空格
3.如果字符串中有空格的话就用双引号包住字串
4.以#开头的行是注释
5.Actions(动作) and Services(服务)这两个关键字开头的行表示一个新的语句段的开端,后面的Commands(命令),Options(选项)都属于该语句段

6.Services(服务)关键字名字具有唯一性,第二次出现的重名Services将会被忽略。


init.rc是主要rc文件,init程序在启动时就会加载这个文件。

Android N较之前的版本上做了特别的改动,为/system,/vendor,/odm分区分别创建了/etc/init/目录,系统中编译出的可执行service必须有对应的rc文件一起内置到/system,/vendor,/odm分区的/etc/init/目录中,对应的rc文件应该还包含与其服务相关联的任何操作。mk文件中通过LOCAL_INIT_RC来指明service对应的rc文件。

#system/core/logcat/Android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := logpersist.start
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_INIT_RC := logcatd.rc
LOCAL_MODULE_PATH := $(bin_dir)
LOCAL_SRC_FILES := logpersist
ALL_TOOLS := logpersist.start logpersist.stop logpersist.cat
LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,$(filter-out $(LOCAL_MODULE),$(ALL_TOOLS)),ln -sf $(LOCAL_MODULE) $(TARGET_OUT)/bin/$(t);)
include $(BUILD_PREBUILT)


init.rc通过imports关键字引入了init.${ro.hardware}.rc,并在执行mount_all指令挂载分区时,会加载一下目录中的rc文件,并在合适的时机运行这些服务和操作。
/system/etc/init ——包含系统核心服务的定义,如SurfaceFlinger、MediaServer、Logcatd等。
/vendor/etc/init ——OC厂商针对SOC核心功能定义的一些服务。比如高通、MTK某一款SOC的相关的服务。
/odm/etc/init ——OEM/ODM厂商如小米、华为、OPP其产品所使用的外设以及差异化功能相关的服务。


下面具体分析相应的关键字

Actions(动作)
一般格式:

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

Actions(动作)是对某事件的响应过程,当trigger事件触发时就依次执行command。在系统中发生相应事件时就依次匹配各个rc中的trigger,把满足条件的Actions都加入到执行队列中(除非队列中已经存在)
常见的触发事件有:
1.boot
这是init执行后第一个被触发Trigger,也就是在 /init.rc被装载之后执行该Trigger
2.<name>=<value>
当属性<name>被设置成<value>时被触发。例如,
on property:vold.decrypt=trigger_reset_main
class_reset main
3.device-added-<path>
当设备节点被添加时触发
4.device-removed-<path>
当设备节点被移除时添加
5.service-exited-<name>
会在一个特定的服务退出时触发


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.

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_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_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.

domainname <name>
Set the domain name.

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.

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.

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.

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.

load_all_props
Loads properties from /system, /vendor, et cetera. This is included in the default init.rc.

load_persist_props
Loads persistent properties when /data has been decrypted. This is included in the default init.rc.

loglevel <level>
Sets the kernel log level to level. Properties are expanded within level.

mkdir <path> [mode] [owner] [group]
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.

mount_all <fstab> [ <path> ]\* [--<option>]
Calls fs_mgr_mount_all on the given fs_mgr-format fstab and imports .rc files at the specified paths (e.g., on the partitions just mounted) with optional options "early" and "late". Refer to the section of "Init .rc Files" for detail.

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, eg: barrier=1,noauto_da_alloc

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.

restorecon_recursive <path> [ <path>\* ]
Recursively restore the directory tree named by path to the security contexts specified in the file_contexts configuration.

rm <path>
Calls unlink(2) on the given path. You might want to use "exec -- rm ..." instead (provided the system partition is already mounted).

rmdir <path>
Calls rmdir(2) on the given path.

setprop <name> <value>
Set system property name to value. Properties are expanded within value.

setrlimit <resource> <cur> <max>
Set the rlimit for a resource.

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.
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.

symlink <target> <path>
Create a symbolic link at path with the value target

sysclktz <mins_west_of_gmt>
Set the system clock base (0 if system clock ticks in GMT)

trigger <event>
Trigger an event. Used to queue an action from another action.

umount <path>
Unmount the filesystem mounted at that path.

verity_load_state
Internal implementation detail used to load dm-verity state.

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.

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.

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.


Services(服务)
Services就是可执行程序,由init程序来运行或者重启,可以在option中指定退出时是否重启
一般格式:

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



Options(选项)
Options是Services中的可选项
常用的Options有:
console [<console>]
This service needs a console. The optional second parameter chooses a specific console instead of the default. The default "/dev/console" can be changed by setting the "androidboot.console" kernel parameter. In all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be specified as just "console tty0".

critical
This is a device-critical service. If it exits more than four times in four minutes, the device will reboot into recovery mode.

disabled
This service will not automatically start with its class. It must be explicitly started by name.

setenv <name> <value>
Set the environment variable name to value in the launched process.

socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
Create a unix domain socket named /dev/socket/name and pass its fd to the launched process. type must be "dgram", "stream" or "seqpacket". User and group default to 0. 'seclabel' is the SELinux security context for the socket. It defaults to the service security context, as specified by seclabel or computed based on the service executable file security context. For native executables see libcutils android_get_control_socket().

file <path> <type>
Open a file path and pass its fd to the launched process. type must be "r", "w" or "rw". For native executables see libcutils android_get_control_file().

user <username>
Change to 'username' before exec'ing this service. Currently defaults to root. (??? probably should default to nobody) As of Android M, processes should use this option even if they require Linux capabilities. Previously, to acquire Linux capabilities, a process would need to run as root, request the capabilities, then drop to its desired uid. There is a new mechanism through fs_config that allows device manufacturers to add Linux capabilities to specific binaries on a file system that should be used instead. This mechanism is described on http://source.android.com/devices/tech/config/filesystem.html. When using this new mechanism, processes can use the user option to select their desired uid without ever running as root. As of Android O, processes can also request capabilities directly in their .rc files. See the "capabilities" option below.

group <groupname> [ <groupname>\* ]
Change to 'groupname' before exec'ing this service. Additional groupnames beyond the (required) first one are used to set the supplemental groups of the process (via setgroups()). Currently defaults to root. (??? probably should default to nobody)

capabilities <capability> [ <capability>\* ]
Set capabilities when exec'ing this service. 'capability' should be a Linux capability without the "CAP_" prefix, like "NET_ADMIN" or "SETPCAP". See http://man7.org/linux/man-pages/man7/capabilities.7.html for a list of Linux capabilities.

seclabel <seclabel>
Change to 'seclabel' before exec'ing this service. Primarily for use by services run from the rootfs, e.g. ueventd, adbd. Services on the system partition can instead use policy-defined transitions based on their file security context. If not specified and no transition is defined in policy, defaults to the init context.

oneshot
Do not restart the service when it exits.

class <name> [ <name>\* ]
Specify class names for the service. All services in a named class may be started or stopped together. A service is in the class "default" if one is not specified via the class option. Additional classnames beyond the (required) first one are used to group services. animation class 'animation' class should include all services necessary for both boot animation and shutdown animation. As these services can be launched very early during bootup and can run until the last stage of shutdown, access to /data partition is not guaranteed. These services can check files under /data but it should not keep files opened and should work when /data is not available.

onrestart
Execute a Command (see below) when service restarts.

writepid <file> [ <file>\* ]
Write the child's pid to the given files when it forks. Meant for cgroup/cpuset usage. If no files under /dev/cpuset/ are specified, but the system property 'ro.cpuset.default' is set to a non-empty cpuset name (e.g. '/foreground'), then the pid is written to file /dev/cpuset/cpuset_name/tasks.

priority <priority>
Scheduling priority of the service process. This value has to be in range -20 to 19. Default priority is 0. Priority is set via setpriority().

namespace <pid|mnt>
Enter a new PID or mount namespace when forking the service.

oom_score_adjust <value>
Sets the child's /proc/self/oom_score_adj to the specified value, which must range from -1000 to 1000.


shutdown <shutdown_behavior>
Set shutdown behavior of the service process. When this is not specified, the service is killed during shutdown process by using SIGTERM and SIGKILL. The service with shutdown_behavior of "critical" is not killed during shutdown until shutdown times out. When shutdown times out, even services tagged with "shutdown critical" will be killed. When the service tagged with "shutdown critical" is not running when shut down starts, it will be started.



Imports(引用)
一般格式:
import <path>

import关键字不是命令,所以它不会作为Action的一部分发生,而是在解析文件时执行导入,只有在下面3种情况下init程序才会import rc文件:
1.When it imports /init.rc or the script indicated by the property ro.boot.init_rc during initial boot.
2.When it imports /{system,vendor,odm}/etc/init/ for first stage mount devices immediately after importing /init.rc.
3.When it imports /{system,vendor,odm}/etc/init/ or .rc files at specified paths during mount_all.



Properties
通过System Properties查看service state
通过init.svc.<name>来查看services的状态,name为services的名称,状态包括:"stopped", "stopping", "running", "restarting"




Boot timing
System Properties中记录了一些启动时间相关的属性:

ro.boottime.init
Time after boot in ns (via the CLOCK_BOOTTIME clock) at which the first stage of init started.

ro.boottime.init.selinux
How long it took the first stage to initialize SELinux.

ro.boottime.init.cold_boot_wait
How long init waited for ueventd's coldboot phase to end.

ro.boottime.<service-name>
Time after boot in ns (via the CLOCK_BOOTTIME clock) that the service was first started.



Bootcharting
启动图表,可以分析启动时间的详情
分析Log的工具:http://www.bootchart.org/

开启方式:

adb shell 'touch /data/bootchart/enabled'

Log输出路径:/data/bootchart/

Log打包命令:
sudo apt-get install pybootchartgui
# grab-bootchart.sh uses $ANDROID_SERIAL.
$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh

比较两个开机时间的命令:
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
在userdebug或者eng版本上使用Systrace来分析开机时间
已抓去wm和am模块的systrace命令为例:
$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py wm am --boot
这个命令会重启设备,在设备完成开机后按Ctrl+C来生成trace.html报告。由于在persistent properties被加载时才会开始抓去systrace log,所以某些模块的systrace会抓去不到,比如vold, surfaceflinger, and servicemanager,而Zygote能抓取到systrace。




Debugging init
init的stdout和stderr信息都被输出到/dev/null,可以使用logwrapper把stdout和stderr重定向到logcat查看。
例如重定向service akmd的信息:
/system/bin/logwrapper /sbin/akmd

快速编译调试init的命令:
mm -j &&
m ramdisk-nodeps &&
m bootimage-nodeps &&
adb reboot bootloader &&
fastboot boot $ANDROID_PRODUCT_OUT/boot.img



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值