android系统启动流程之init.rc详细分析笔记

        对于Android系统的学习掌握,除了对一些语言基础的要求,如C,C++,Java,shell,makefile等,更要整体去把握系统的架构。对于架构的熟悉入门,首先应该分析android的编译系统结构。而对于系统的启动流程的掌握,最好是深入分析init.rc、init.xx.rc等文件。这些文件相对来说代码量少,比较简单,而且对系统的整体认识有很大的帮助。以前在工作中经常要用到init.rc相关的知识,但是没有系统的去分析整体,最近写成了笔记,分享出来!


关于init.rc的几点说明:
1).在android源码目录下面jb\system\core\init\readme.txt文件中有init.rc语法的详细定义
  注意:readme.txt没有和android的版本一起更新,所以在新版本的android中,增加了一些commands、options等,在readme.txt中 没有介绍。 还是看init目录下面的源码最为准确

2).解析init.rc,init.xx.rc的相关文件目录system/core/init/

3).init.c 、init.rc init.xx.rc 等最终会编译到ramdisk.img(根文件系统)中,和kernel一起打包成boot.img。android启动后每次都会从boot.img中解压出init.c等文件到内存,所以要修改必须修改替换boot.img。

4).在init.rc中启动的服务,都是以一个进程的形式运行,属于android的本地服务。通过在终端输入PS命令可以查看在运行的相应进程,他们的ppid都为1,代表init进程。 init进程也是android系统启动的第一个应用进程

5).init.rc中所有的语句都是以行为单位的(每个语句都是单独写在一行里面)

6).注释行以“#”开头

7).Actions 和 Services表示一个新的段落section的开始。
 所有的commands和options 都是归属于上方最近的一个段落。在第一个段落之前的commands和options是无效的。

8).Actions and Services
不能重名,如果重名,后面的定义会被忽略(readme.txt说明)。
但是实际项目中同一个init.xx.rc中有重名的action,也可以正常使用。多个init.xx.rc中action也允许有重名, 比如 boot,init 等在多个rc文件中出现。services应该不能重名


init.rc (Android Init Language)语法详解:

1.init语法的四个组成原件:
Actions  :动作 ,使用格式: on <Triggers>,下面行跟各种command
Commands :命令  
Services :服务  使用格式 : service <name> <pathname> [ <argument> ]* ,下面行可以添加Options
Options : 选项

2.init.rc中三大模块:
1). import 导入其他的init.xx.rc文件。
2). 以action动作为触发点的一系列命令
3). 带有各种Options的一系列services的定义


import /init.${ro.hardware}.rc
通过cat proc/cpuinfo可以查看ro.hardware的值=Hardware的值

on <trigger>    //action 模型
   <command>
   <command>
   <command>
   ....
  
service <name> <pathname> [ <argument> ]*   (services可以带有多个参数和选项)
   <option>
   <option>
   ...  

3.对Actions官方描述的一些理解 :
当action的trigger被匹配后,action会被加入到动作执行队列中,在队列中的action按队列顺序被执行,每个action下面的command也是按顺序执行。按这个理论,在init.rc中action、command、service的执行顺序主要是和它们的触发时间有关,如果都是开机启动时执行,应该也和代码顺序有关。(有兴趣可以验证一下、想深入了解解析过程,可以查看源码目录init下面的init_parser.c等文件)


4.Triggers : 跟在on后面的动作名,用来触发action下面command的执行

1).android常用的triggers的名字:
  early-init,init,early-fs,fs,post-fs,early-boot,boot (这些都是在init.c中触发)

2).可以自定义一些triggers,并选择合适的触发方式 (例如:关机充电功能,可以只启动charger服务进程)

3).<name>=<value> 形式,如:on property:ro.debuggable=1

4). device-added-<path>
    device-removed-<path>      
   Triggers of these forms occur when a device node is added or removed
   一个设备节点/dev/XXX添加或者删除时可以触发一个action,这个可以很好的去利用
 
5).service-exited-<name>  
   Triggers of this form occur when the specified service exits.
   当某个服务退出时,可以触发一个action


5.option 选项:(用于services下面)
android新版本上增加的一些options可以通过源码查看对应作用
init_parser.c--》lookup_keyword(const char *s)--》parse_line_service() 或者 --》parse_line_action()


1).class <class_name>  
说明服务属于class_name这个类。缺省值service属于 “default” 类。同一个class下面的服务可以一起启动或停止。

2).disabled 
表示当这个服务所在的class启动的时候,服务不会自动启动,
要用start server_name 或 property_set("ctl.start", server_name);才能启动。
 
3).oneshot  
当服务退出后,不会再重新启动,如果没有加这个option,则服务默认退出后又会重新重启

4).user <username> 
   执行服务之前,先声明服务的用户名,缺省值应该为root用户.
   如果你的进程要求具有Linux内核能力,必须保证它的用户为root(没有完全明白,实例?)


5).group <groupname> [ <groupname> ]*
  执行服务之前,先声明服务所属组名,可以一次声明属于多个组。
   声明多个组时,除第一个组名外,其他的为服务的补充组名(调用接口 setgroups()).
  
6).onrestart   + command
服务重启的时,会执行onrestart后面的command.
eg:onrestart restart media 重启名为media的服务
   
7).setenv <name> <value>      
在当前服务进程中设置环境变量name的值为value。
注意:setenv定义的环境变量仅在本进程内生效,退出该进程,或者关闭相应的程序运行窗口,该环境变量即无效)
程序中可通过getenv("name")接口获取这个环境变量的值
setenv和export 的区别:
setenv  csh ,本进程生效,退出后,变量无效
export  bash ,全局生效,一直存在
格式:
export key=value
setenv key value

8).critical   
声明为设备的循环服务。如果服务在四分钟内退出了四次,则设备会进入recovery模式
使用实例servicemanager、ueventd等服务

9).socket <name> <type> <perm> [ <user> [ <group> ] ]  
创建名为/dev/socket/<name>的unix domain socket ,并把它的句柄fd传给本服务进程
 <type> 必须为 "dgram", "stream" or "seqpacket".User and group default to 0 ,也就是root.
 
  
6.command   :(action下面的一系列命令)

常用命令:

1).import <filename>        
  导入init.XX.rc、xxx.conf等文件
   Parse an init config file, extending the current configuration.

2).chmod <octal-mode> <path>
   Change file access permissions.

3).chown <owner> <group> <path>
   Change file owner and group.
  
4).chdir <directory>
   Change working directory.
  
5).chroot <directory> 
  改变进程根目录
  
6).insmod <path>   
  加载XX.ko驱动模块

7).start <service>
   Start a service running if it is not already running.

8).stop <service>
   Stop a service from running if it is currently running.

9).class_start <serviceclass>
   Start all services of the specified class if they are not already running.

10).class_stop <serviceclass>
   Stop all services of the specified class if they are currently running.
     
   class_reset <serviceclass>   //重启class下面所有的服务
     
11).setprop <name> <value>  
   Set system property <name> to <value>.
   通过getprop命令可以查看当前系统的属性值
  
12).export <name> <value>       
  设置全局环境变量,这个变量值可以被所有进程访问(全局的,一直存在)
  在代码中通过value = getenv("name")接口可以获取这个环境变量的值
  
13).mkdir <path> [mode] [owner] [group]
   创建目录,后面项缺省值为 mode,owner,group: 0755 root root

14).trigger <event>
   Trigger an action.  Used to queue an action from another action.
   例:trigger post-fs-data

15).exec <path> [ <argument> ]*     
   执行<path>指定的Program,并可以带有执行参数。
   exec在调用进程内部执行一个可执行文件,并会阻塞当前进程,直到运行完成。
   最好避免和那些builtin commands一样使用exec命令,否则容易造成阻塞 or stuck ( maybe there should be a timeout?)

16).ifup <interface>
   启动某个网络接口,使其为up状态,通过netcfg可以查看,ifup eth0  等价于 netcfg eth0 up 功能一样
  
17).hostname <name>
   设置设备的主机名,一般默认设置为localhost,可以在终端通过hostname new_name进行修改

18).domainname <name>
   设置网络域名localdomain

19).mount <type> <device> <dir> [ <mountoption> ]*
    把device挂接到dir目录下面,文件系统类型为type。
   <mountoption>s include "ro", "rw", "remount", "noatime", “nosuid”......,具体可查看linux的mount命令说明
  
20).setkey
   TBD  == to be determined 暂时没有使用

21).setrlimit <resource> <cur> <max>
  设置本服务进程的资源上限值。(使用例子??)

22).symlink <target> <path>   
   path 链接到 ---》target ;创建符号链接

23).sysclktz <mins_west_of_gmt>  
  设置系统时区(0 if system clock ticks in GMT)

24).wait <path> [ <timeout> ]
 轮询查找给定的文件path是否存在,如果找到或者超时则返回默认超时为5秒。(使用实例???)

25).write <path> <string> [ <string> ]*
   打开一个文件,利用write命令写入一个或多个字符串


7. Properties
----------
Init updates some system properties to provide some insight into
what it's doing:

init.action
   Equal to the name of the action currently being executed or "" if none

init.command
   Equal to the command being executed or "" if none.

init.svc.<name>
   State of a named service ("stopped", "running", "restarting")
  属性状态,getprop命令可以查看。property_set接口函数、ctl.start、ctl.stop来设置


8.实际的一些例子,基于android4.2.1:


1).readme.txt自带的一些例子(只是整理一些有代表性的):


on boot
   export PATH /sbin:/system/sbin:/system/bin

   mount tmpfs tmpfs /dev
  mount yaffs2
mtd@system /system

   write /proc/cpu/alignment 4
  
   import /system/etc/init.conf 
   //导入相应的配置文件

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 调试注意点:
---------------
默认的,在系统init进程中启动的程序(如XX.rc中定义的服务等) ,不能通过logcat查看相关log信息
为了调试,需要增加执行logwrapper,才能通过logcat查看log信息,(之前调试可以直接查看log信息啊,有待验证)
如:service akmd /system/bin/logwrapper /sbin/akmd 
可以通过logcat查看akmd服务中的log信息。


2).实际项目中的一些典型例子(只是整理一些有代表性的)

init.rc文件中的一些参考例子:
           
import /init.${ro.hardware}.rc
on early-init

    write /proc/1/oom_adj -16

    # Set the security context for the init process.
    # This should occur before anything else (e.g. ueventd) is started.
    setcon u:r:init:s0 
    
    start ueventd
    mkdir /mnt 0775 root system

on init

sysclktz 0
loglevel 3    设置log输出等级

# setup the global environment
    export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
    export ANDROID_BOOTLOGO 1

    symlink /system/etc /etc     
    mount tmpfs tmpfs /mnt/secure mode=0700,uid=0,gid=0
    write /proc/sys/kernel/panic_on_oops 1
  
    mount cgroup none /dev/cpuctl cpu
    chown system system /dev/cpuctl
    chmod 0660 /dev/cpuctl/tasks

on fs
# mount mtd partitions
    #mount yaffs2
mtd@system /system ro remount
 
on post-fs
    mount rootfs rootfs / shared rec
    mount tmpfs tmpfs /mnt/secure private rec
    # We restorecon /cache in case the cache partition has been reset.
    restorecon /cache  

on post-fs-data
   
    write /proc/apanic_console 1
    mkdir /data/misc 01771 system misc
   mkdir /data/misc/adb 02750 system shell 
    setprop vold.post_fs_data_done 1


on boot

# basic network init
    ifup lo
    hostname localhost
    domainname localdomain

# set RLIMIT_NICE to allow priorities from 19 to -20
    setrlimit 13 40 40

    class_start core
    class_start main

on charger
    class_start charger

on property:vold.decrypt=trigger_reset_main
    class_reset main

on property:vold.decrypt=trigger_load_persist_props
    load_persist_props
    //加载用户空间设置的系统属性persist_props 

on property:vold.decrypt=trigger_post_fs_data
    trigger post-fs-data

service ueventd /sbin/ueventd
    class core
    critical
    seclabel u:r:ueventd:s0 

on property:selinux.reload_policy=1
    restart ueventd
    restart installd

service console /system/bin/sh
    class core
    console       //requires console
    disabled
    user shell
    group log

on property:ro.debuggable=1
    start console

# adbd is controlled via property triggers in init.<platform>.usb.rc
service adbd /sbin/adbd
    class core
    socket adbd stream 660 system system
    disabled
    seclabel u:r:adbd:s0
    ioprio rt 4 
  ioprio be 2
IoSchedClass, usage: ioprio <rt|be|idle> <ioprio 0-7>\n . 
  
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical  //添加了此选项,如果servicemanager在四分钟内退出了四次,则设备会进入recovery模式
    onrestart restart zygote  //如果servicemanager服务重启,则zygote服务也会重启

 
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server   (后面都是所带参数app_process)
    class main
    socket zygote stream 660 root system
    socket keystore stream 666
    onrestart write /sys/power/state on  //如果zygote服务重启,则执行write命令,写state为on

 
init.hardware.rc内容 :

import /init.usb.rc

on init
    export EXTERNAL_STORAGE /mnt/sdcard    getenv("EXTERNAL_STORAGE") 获取变量值/ dalvik_system_Zygote.cpp
    mkdir /mnt/sdcard 0000 system system  
    symlink /mnt/sdcard /sdcard
   
  #通过USB接口的U盘虚拟成SD卡的操作
  #export EXTERNAL_STORAGE /mnt/usb/sda1
    #mkdir /mnt/usb/sda1 0000 system system
    #symlink /mnt/usb/sda1 /sdcard
    #symlink /mnt/usb/sda1 /mnt/sdcard
  
on early-init
    mount tmpfs tmpfs /mnt/usb mode=0755,gid=1000

on init
    mkdir /var 0775 system system

on fs
  mount -o size=110m -t tmpfs tmpfs /dev/cache mode=0777,gid=1000 
    mount ext4 /dev/block/mmcblk0p4 /system wait ro noatime block_validity nodiscard data=ordered journal_checksum 
    mount ext4 /dev/block/mmcblk0p5 /data wait nosuid nodev noatime block_validity nodiscard data=ordered journal_checksum
    mount ext4 /dev/block/mmcblk0p7 /tvservice wait ro noatime block_validity nodiscard data=ordered journal_checksum
 
on post-fs
    command
   
on post-fs-data
    write /proc/sys/kernel/core_pattern /var/coredump.%p.gz

on boot

# After launcher is displayed, trigger related drivers initialization
on property:init.svc.bootanim=stopped// 开机后启动加载或者启动某些服务,提高开机速度
    insmod /system/lib/modules/usb-storage.ko
   
# bugreport is triggered by holding down volume down, volume up and power
service bugreport /system/bin/bugmailer.sh -v
    class main
    disabled
    oneshot
    keycodes 114 115 116   
 //keycodes for triggering this service via /dev/keychord 。参见init.h





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值