Android启动后,系统执行的第一个进程是一个称为init 的可执行程序。它提供了以下的功能:设备管理、解析启动脚本、执行基本的功能、启动各种服务。代码的路径:system/core/init,结果是一个可执行文件:init,在根文件系统root下。这个init 的可执行文件是系统运行的第一个用户空间的程序,它以守护进程的方式运行。启动脚本则就是下面要讲的Init.rc。
=============解析Android启动脚本init.rc===================
init.rc,可以在系统的初始化过程中进行一些简单的初始化操作。这个脚本被直接安装到目标系统的根文件系统中,被 init可执行程序解析。它主要包含了四种类型的语句:Action,Commands,Services,Options.其中 Action 和 services 显式声明了一个语句块,以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
setprop:设置属性及对应的值。类似setprop selinux.reload_policy 1。那么开机后在JAVA层和CPP层都可以访问这个值。
start
stop
symlink:创建一个符号链接
sysclktz:设置系统基准时间
write:往指定的文件写字符串
mount:类似于 linux 的 mount 指令
chdir
(2)Actions(动作)表示一系列的命令,通常在Triggers(触发条件,关键字on)中调用,动作和触发条件的形式为:
on
动作的使用示例如下:
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
跟Services搭配使用的常用Options(选项)解释如下:
socket:在/dev/socket/下创建一个 unix domain 的 socket
user:在执行此服务之前先切换用户名。当前默认为 root
group:类似于 user,切换组名
oneshot:表示该服务只启动一次;而如果没有oneshot选项,这个可执行程序会一直存在,如果可执行程序被杀死,则会重新启动。
class:类属,即可以为多个 service 指定一个相同的类属,方便操作同时启动或停止。可为main或者core等
onrestart:当服务重启时执行一条指令
disabled:服务不会自动运行,必须显式地启动。启动方法:(0)sh中,以start 服务名(1)adb命令行:#setprop ctl.start bootanim #setprop ctl.stop bootanim(2)C代码:property_set(“ctl.start”, “bootanim”); property_set(“ctl.stop”, “bootanim”);(3)JAVA代码,就是SystemProperties.set
(4)以上说明了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无法改变权限的问题
添加了chmod语句后,开机发现权限仍然没变。最后发现要先修改/system ro权限为rw,即mount ext4 /dev/block/system /system rw wait noatime nodiratime,而且chmod要放在该句同属的on fs段才可以(on fs挂载文件系统)
(5)如何知道一个service是否还在运行
用getprop init.svc.$service_name即可,service_name即定义的服务名。比如
getprop init.svc.mcucomm
running
================init.rc中启动sh文件================
假设,我们通过adb调试命令调好了一个外设的硬件模块,下一步的动作,需要让系统开机自动跑这些命令并正常启动模块的工作。这个时候,就需要用到sh将这些命令组合起来,放到init.rc中就可以实现这个目的。shell内容如下:
#!/system/bin/sh
PKG_DIR=/system/lib/modules
APP_DIR=/system/bin
cd $PKG_DIR
CUR_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_DIR
CUR_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 -d
sleep 1
./qlulpsh_loader_app -c 1 -a 0002
echo "Starting SensorHub..."
echo 1 > /sys/devices/virtual/QL_Sensors/qlulpsh/intr_enable
echo 16 > /sys/devices/virtual/QL_Sensors/qlulpsh/FFE_RunCnt
sleep 1
echo "Starting sensorservice..."
sensorservice &
注意:(1)两个可执行文件前要加./,否则提示可执行文件not found,需指明当前目录下。(2)考虑硬件的实际执行情况,sh中有sleep语句,有些读操作要等待真实硬件初始化OK。(3)sensorservice &启动安卓系统sensor服务。
在init.rc中,补上如下语句,用service启动一个shell。
# SenHub scripts
service myshell /system/bin/sensorhub_init.sh
oneshot
===================JAVA中跑shell=============
如果在java中跑shell命令。systemui中可跑,app中老是失败。
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
========================文件和文件夹拷贝=====================
上述执行shell拷贝的功能,用java函数也可以完成。
(1)文件拷贝,systemui中试验成功
public void copyVideoFile(String oldPath, String newPath) {
try {
int bytesum = 0;
int byteread = 0;
File oldfile = new File(oldPath);
File newfile = new File(newPath);
if (oldfile.exists()) {
Log.d("Clock","oldfile exists ");
if(!newfile.exists()){
Log.d("Clock","newfile no exists ");
InputStream inStream = new FileInputStream(oldPath); //?áè??-???t
FileOutputStream fs = new FileOutputStream(newPath);
byte[] buffer = new byte[1024];
while ( (byteread = inStream.read(buffer)) != -1) {
bytesum += byteread;
fs.write(buffer, 0, byteread);
}
inStream.close();
fs.close();
}
}
}
catch (Exception e) {
Log.d("Clock","copy video error");
e.printStackTrace();
}
}
使用时用copyVideoFile("/system/BerylliumVideo.mp4","/storage/sdcard0/Movies/BerylliumVideo.mp4");
(2)文件夹拷贝
public void copyFolder(String oldPath, String newPath) {
try {
(new File(newPath)).mkdirs();
File a=new File(oldPath);
String[] file=a.list();
File temp=null;
for (int i = 0; i < file.length; i++) {
if(oldPath.endsWith(File.separator)){
temp=new File(oldPath+file[i]);
}
else{
temp=new File(oldPath+File.separator+file[i]);
}
if(temp.isFile()){
FileInputStream input = new FileInputStream(temp);
FileOutputStream output = new FileOutputStream(newPath + "/" +
(temp.getName()).toString());
byte[] b = new byte[1024 * 5];
int len;
while ( (len = input.read(b)) != -1) {
output.write(b, 0, len);
}
output.flush();
output.close();
input.close();
}
if(temp.isDirectory()){
copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);
}
}
}
catch (Exception e) {
System.out.println("copy folder error");
e.printStackTrace();
}
}
使用时copyFolder("/system/filetest","/storage/sdcard0/Movies/filetest");
参考原文: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