init进程 && 解析启动脚本init.rc && init.rc中启动sh文件 && JAVA中跑shell

来源:互联网 发布:mac charles 简书 编辑:程序博客网 时间:2024/05/17 08:25

        Android启动后,系统执行的第一个进程是一个称为init 的可执行程序。它提供了以下的功能:设备管理、解析启动脚本、执行基本的功能、启动各种服务。代码的路径:system/core/init,结果是一个可执行文件:init,在根文件系统root下。这个init 的可执行文件是系统运行的第一个用户空间的程序,它以守护进程的方式运行。启动脚本则就是下面要讲的Init.rc。

====================================解析Android启动脚本init.rc===========================================

        init.rc,可以在系统的初始化过程中进行一些简单的初始化操作。这个脚本被直接安装到目标系统的根文件系统中,被 init可执行程序解析。它主要包含了四种类型的语句:Action,Commands,Services,Options.其中 Action 和 services 显式声明了一个语句块,一个语句块以 Service 或 On 开头的语句块,以Service 开头的 Section 叫做服务,而以 On 开头的叫做动作(Action)。而 commands 和 options 属于最近声明的语句块。

(1) Commands是一些基本的操作,例如:
    mkdir /sdcard 0000 system system
    mkdir /system
    mount tmpfs tmpfs /sqlite_stmt_journals size=4m

这些命令在init可执行程序中被解析,然后调用相关的函数来实现,可在Keywords.h (system\core\init)中查到命令和函数的对应关系。

        常见命令如下:

export:设置全局环境参数,此参数被设置后对所有进程都有效.

class_start:启动指定类属的所有服务,如果服务已经启动,则不再重复启动

class_stop:停止指定类属的所有服务

insmod:安装模块到指定路径

mkdir <path> [mode] [owner] [group]:用指定参数创建一个目录,在默认情况下,创建的目录读取权限为 755。用户名为 root,组名为 root

setprop:设置属性及对应的值

start <service>:如果指定的服务未启动,则启动它

stop <service>:如果指定的服务当前正在运行,则停止

symlink:创建一个符号链接

sysclktz:设置系统基准时间

write:往指定的文件写字符串

mount:类似于 linux 的 mount 指令

chdir <directory> :改变工作目录
(2)Actions(动作)表示一系列的命令,通常在Triggers(触发条件,关键字on)中调用,动作和触发条件的形式为:
   on <trigger>
      <command>
      <command>
动作的使用示例如下:
    on init
    export PATH /sbin:/system/sbin:/system/bin:/system/xbin
    mkdir /system
on init表示一个触发条件。

        还有on property可以用于判断是否满足属性,满足xx条件的时候,执行一系列操作,比如:

on property:gpsId=GPS_ID_3332
    insmod /system/drivers/gps.ko

(3)Services(服务)是指那些需要在系统初始化时就启动或退出时自动重启的程序,这些service的源码都会在 frameworks\base\cmds\目录下。
service vold /system/bin/vold
    socket vold stream 0660 root mount
service bootsound /system/bin/playmp3
    user media
    group audio
    oneshot
vold和bootsound分别是两个服务的名称,/system/bin/vold和/system /bin/playmp3分别是他们所对应的可执行程序。

        跟Services搭配使用的常用Options(选项)解释如下:

socket:在/dev/socket/下创建一个 unix domain 的 socket

user:在执行此服务之前先切换用户名。当前默认为 root

group:类似于 user,切换组名

oneshot:表示该服务只启动一次;而如果没有oneshot选项,这个可执行程序会一直存在,如果可执行程序被杀死,则会重新启动。

class:类属,即可以为多个 service 指定一个相同的类属,方便操作同时启动或停止。

onrestart:当服务重启时执行一条指令

disabled:服务不会自动运行,必须显式地通过服务器来启动


         以上说明了init.rc中各个组成部分,这些内容是有固定的执行顺序,这个顺序由early-init, init, early-boot, boot这四个关键字决定。一个典型的rc文件的写法如下:
on early-init
--------------

on init
--------------

on early-boot
--------------

on boot
--------------

rc文件中这4个部分是可以打乱顺序随便写的,但是解析完了以后的执行顺序确实固定的,执行顺序如下: early-init、init、early-fs,fs,post-fs,post-fs-data,early-boot,boot。

(4)碰到的问题

        添加了chmod语句后,开机发现权限仍然没变。最后发现要先修改/system ro权限为rw,即mount ext4 /dev/block/system  /system rw wait noatime nodiratime,而且chmod要放在该句同属的on fs段才可以,如果放在init.rc最后面,权限也是改不掉的。

==========================================init.rc中启动sh文件=====================================

         假设,我们通过adb调试命令调好了一个外设的硬件模块,下一步的动作,需要让系统开机自动跑这些命令并正常启动模块的工作。这个时候,就需要用到sh将这些命令组合起来,放到init.rc中就可以实现这个目的(不要放到init.project.rc中,会影响到WIFIBT)。

        出于执行权限原因,ko文件可以放到vendor的/system/lib/modules下(不能放到vendor对应的/data目录,RELEASE版本/data无权限insmod),可执行文件包括shell则放到vendor的/system/bin下,这样确保任何时候都可以执行。

#!/system/bin/shPKG_DIR=/system/lib/modulesAPP_DIR=/system/bincd $PKG_DIRCUR_PKG_DIR=`pwd`echo "CUR_PKG_DIR = $CUR_PKG_DIR"insmod $PKG_DIR/accel_qlulpsh.ko insmod $PKG_DIR/mag_qlulpsh.ko insmod $PKG_DIR/gyro_qlulpsh.ko insmod $PKG_DIR/pedometer_qlulpsh.ko insmod $PKG_DIR/gestures_qlulpsh.ko insmod $PKG_DIR/contexts_qlulpsh.ko cd $APP_DIRCUR_APP_DIR=`pwd`echo "CUR_APP_DIR = $CUR_APP_DIR"#Program the Sensor hub echo "SensorHub Programming using loader APP"sleep 1./qlulpsh_loader_app -i ./ulpsh_s2_main.shexe -b 1 -s 1 -t 10 -dsleep 1./qlulpsh_loader_app -c 1 -a 0002echo "Starting SensorHub..."echo 1 > /sys/devices/virtual/QL_Sensors/qlulpsh/intr_enableecho 16 > /sys/devices/virtual/QL_Sensors/qlulpsh/FFE_RunCntsleep 1echo "Starting sensorservice..."sensorservice &
注意:(1)两个可执行文件前要加./,否则提示可执行文件not found,需指明当前目录下。(2)考虑硬件的实际执行情况,sh中有sleep语句,有些读操作要等待真实硬件初始化OK。(3)sensorservice &启动安卓系统sensor服务。

        在init.rc中,补上如下语句,用service启动一个shell。

# SenHub scriptsservice myshell /system/bin/sensorhub_init.shoneshot

==========================================JAVA中跑shell=====================================

如果在java中跑shell命令

 void cpimage() { String result;        try {                       Process p = Runtime.getRuntime().exec("cp /system/BerylliumVideo.mp4 /storage/sdcard0/Movies");            int status = p.waitFor();            if (status == 0) {                result = "Pass";            } else {                result = "Fail: IP addr not reachable";            }        } catch (IOException e) {            result = "Fail: IOException";        } catch (InterruptedException e) {            result = "Fail: InterruptedException";        }    }
如果在java中跑shell脚本
     void cpimage() { String result;        try {                       Process p = Runtime.getRuntime().exec("system/bin/init.BerylliumVideo.sh");            int status = p.waitFor();            if (status == 0) {                result = "Pass";            } else {                result = "Fail";            }        } catch (IOException e) {            result = "Fail: IOException";        } catch (InterruptedException e) {            result = "Fail: InterruptedException";        }    }

shell内容:

if [ ! -e /storage/sdcard0/Movies/BerylliumVideo.mp4 ];then cp /system/BerylliumVideo.mp4 /storage/sdcard0/Movies/fi



参考原文:http://hi.baidu.com/albertchen521/blog/item/4ac8d500f894fddf277fb59b.html

参考原文:http://blog.csdn.net/jiajie961/article/details/6047219

参考原文:http://hi.baidu.com/donghaozheng/blog/item/e2f5045577cb73c8b645aec0.html