首页 > 代码库 > Android初始化语言(init.rc语法)

Android初始化语言(init.rc语法)

本文为 ANDROID_SOURCE/system/core/init/readme.txt 的译文。


安卓初始化语言

安卓初始化语言包括四种类型的语句,它们是:

  • 动作 Action
  • 命令 Command
  • 服务 Service
  • 选项 Option

所有语句都是面向行的,以空格分割每行包含的若干token。C风格的反斜杠可以用于token中插入空格,双引号同样可以避免空格将文本分为多个token。反斜杠是一行的最后一个字符时,将用于续行(PS:下一行也属于该句)。

以#开头的行(前面有空格也是允许的)是注释。

Action和Service隐式定义了一个新的section(段),所有Command或Option属于最近定义的section。在第一个section之前的Command或Option将被忽略。

Action和Service有唯一的名字。如果有第二个Action或Service定义为和一个已存在的(Action或Service)同名,它将被作为错误忽略掉。


动作 Action

Action是有名字的一系列的命令。Action有一个tirgger(触发器),用于决定该Action应在何时执行。当一个事件发生并匹配了一个Action的trigger,相应的Action将被添加到即将执行(to-be-executed)队列的尾部(除非她已经在队列上了)。

每个action在队列中顺序排列,每个action中的command将会顺序执行。init在执行command的过程中还有执行其他活动(设备节点的创建/销毁,属性设置,进程重启)。

Action具有以下格式:

on <trigger>
   <command>
   <command>
   <command>

服务 Service

Service是init加载的和是退出重启的(可选)程序。Service具有如下格式:

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

选项 Option

Option是Service的修改者。它们影响着init如何及何时运行Service。可用的Option有:

critical
   这是十分关键的服务。如果在四分钟内超过四次,手机将会重启并进入recovery模式。

disabled
   这种类型的服务不会自动启动。它必须明确的使用名字启动。

setenv <name> <value>
   设置环境变量<name>=<value>在加载的进程中。

socket <name> <type> <perm> [ <user> [ <group> [ <context> ] ] ]
   创建一个名为/dev/socket/<name>的UNIX域socket并将fd传递到加载的进程中。
   <type>必须是"dgram", "stream", "seqpacket"中的一种。
   <user>和<group>默认为0.
   <context>是 SELinux socket 安全上下文,默认为service安全级别,可以指定为seclabel或根据service的可执行文件的安全级别计算。

user <username>
   在执行该service前改变用户名,默认为root。如果你的进程请求Linux的特殊能力,就不要用这个命令。需以进入进程仍是root->请求特权->切换到你期望的uid来替换此法。

group <groupname> [ <groupname> ]*
   在执行该service前改变组名。第一个以后的附加组名用于设定进程的附加组(通过setgroups())。当前默认是root。

seclabel <securitycontext>
  在执行服务之前改变安全级别。主要用于从rootfs执行服务,比如ueventd, adbd. 在system分区上可以用基于文件安全级别的策略定义的transition,如果没有指定且没有定义策略的transition,默认是init上下文。
  Change to securitycontext 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
   退出不重启服务(名副其实,一次性)。

class <name>
   为一service指定一个类名,所有有相同类名的service可以一同启动或停止。如果没有用class选项指定类名,该service属于"default"。

onrestart
    在service重启的时候执行。


触发器 Trigger

触发器是可以用来匹配一些种类的事件和用来引发一个行为发生的字符串。

boot
   这是init启动后最先被触发的trigger(在Init.conf被加载以后)。

<name>=<value>
   这种形式额trigger(触发器)属性<name>被设定为<value>时被触发。

device-added-<path>
device-removed-<path>
   这种形式的Triggers(触发器)会在设备节点<path>被添加或移除时触发。

service-exited-<name>
   这种形式的Triggers会在指定的service退出时被触发。


命令 Command

exec <path> [ <argument> ]*
   创建和执行程序(<path>).  这将会阻塞init,直到程序执行完成。由于它不是内置命令,应尽量避免使用exec,它可能会引起init卡死。

export <name> <value>
   在全局环境变量中设在环境变量 <name>为<value>。(这将会被所有在这命令之后运行的进程所继承)

ifup <interface>
   启动网络接口<interface>

import <filename>
   解析一个init配置文件,扩展当前配置。

hostname <name>
   设置主机名。

chdir <directory>
   改变工作目录。

chmod <octal-mode> <path>
   更改文件访问权限。

chown <owner> <group> <path>
   更改文件的所有者和组。

chroot <directory>
  改变进程的根目录。

class_start <serviceclass>
   启动该类service所有尚未运行的服务。

class_stop <serviceclass>
   停止所有该类正在运行的service。

domainname <name>
   设置域名。

enable <servicename>
   改变一个disable的service为enabled,就像他们好像没有明确的关闭一样。如果该service已经应该运行,它会立刻启动。典型的用法是,当bootloader设定一个表示特定的变量,service应该启动。比如:

     on property:ro.boot.myfancyhardware=1
        enable my_fancy_service_for_my_fancy_hardware

insmod <path>
   安装位于<path>的模块(PS:驱动)。

mkdir <path> [mode] [owner] [group]
   在<path>创建一个目录,(可选)使用给定的模式,所有者个组。如果没有提供,该目录将用755权限,所有者为root用户,组为root。

mount <type> <device> <dir> [ <mountoption> ]*
   尝试挂载<device>到<dir>,<device>可能有mtd@name形式,以指定名为name的mtd块设备。
   <mountoption>包括 "ro", "rw", "remount", "noatime", ...

restorecon <path> [ <path> ]*
   恢复名为<path>的文件在file_contexts中配置的的安全级别。自动被init标记正确,不需要用init.rc创建的目录。
restorecon_recursive <path> [ <path> ]*

   递归的恢复<path>指出的目录树中file_contexts配置指定的安全级别。 path不要用shell可写或app可写的目录,如/data/locla/temp, /data/data,或者有类似前缀的(目录)。


setcon <securitycontext>
   设置当前进程的security context为特定的字符串。这是典型的仅用于所有进程启动之前的early-init设置init context。

setenforce 0|1
   设置SELinux系统范围的enfoucing状态。0 is permissive (i.e. log but do not deny), 1 is enforcing.

setkey
   TBD

setprop <name> <value>
   设置系统属性<name>为<value>.

setrlimit <resource> <cur> <max>
   为特定资源设置rlimit.

setsebool <name> <value>
   设置SELinux的bool类型<name>为<value>。   <value> may be 1|true|on or 0|false|off

start <service>
   启动一个服务(如果服务尚未启动)。

stop <service>
   停止服务(如果正在运行)。

symlink <target> <path>
   创建一个符号连接,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>
   触发一个事件。一个动作将另一动作排队。

wait <path> [ <timeout> ]
  poll特定的<path>,出现后返回,或timeout到达。如果timeout没有指定,默认为5秒。

write <path> <string>
   打开一个位于<path>的文件,写入(不是追加)字符串<string>。


属性 Properties

init进程会更新一些系统属性,下面是一些具体的属性:

init.action
   等于当前正在执行的action,或者""若果没有的话。

init.command
   等于当前正在执行的command,或者""如果没有的话。

init.svc.<name>
   一个有名service的状态("stopped", "running", "restarting")

Example init.conf

-----------------

# not complete -- just providing some examples of usage
#
on boot
   export PATH /sbin:/system/sbin:/system/bin
   export LD_LIBRARY_PATH /system/lib

   mkdir /dev
   mkdir /proc
   mkdir /sys

   mount tmpfs tmpfs /dev
   mkdir /dev/pts
   mkdir /dev/socket
   mount devpts devpts /dev/pts
   mount proc proc /proc
   mount sysfs sysfs /sys

   write /proc/cpu/alignment 4

   ifup lo

   hostname localhost
   domainname localhost

   mount yaffs2 mtd@system /system
   mount yaffs2 mtd@userdata /data

   import /system/etc/init.conf

   class_start default

service adbd /sbin/adbd
   user adb
   group adb

service usbd /system/bin/usbd -r
   user usbd
   group usbd
   socket usbd 666

service zygote /system/bin/app_process -Xzygote /system/bin --zygote
   socket zygote 666

service runtime /system/bin/runtime
   user system
   group system

on device-added-/dev/compass
   start akmd

on device-removed-/dev/compass
   stop akmd

service akmd /sbin/akmd
   disabled
   user akmd
   group akmd

Debugging notes

---------------
By default, programs executed by init will drop stdout and stderr into
/dev/null. To help with debugging, you can execute your program via the
Andoird program logwrapper. This will redirect stdout/stderr into the
Android logging system (accessed via logcat).

For example
service akmd /system/bin/logwrapper /sbin/akmd


Android初始化语言(init.rc语法)