Android service启动分析
上文简单描述了Android层面init.c文件的执行过程,最后到了parse init.rc文件,先将init.rc文件开启的各种服务做一个简单分析:
首先,各字段的执行顺序如下,
1. 所有的action运行于service之前
2. 下面为各个section的执行顺序,英文编号的section是系统内建的(写死在init.c中的命令)
1) early-init
a) wait_for_coldboot_done
b) property_init
c) keychord_int
d) console_init
e) set_init_properties
2) init
3) early-fs
4) fs
5) post-fs
f) property_service_init
g) signal_init
h) check_startup
6) early-boot
2. 下面为各个section的执行顺序,英文编号的section是系统内建的(写死在init.c中的命令)
1) early-init
a) wait_for_coldboot_done
b) property_init
c) keychord_int
d) console_init
e) set_init_properties
2) init
3) early-fs
4) fs
5) post-fs
f) property_service_init
g) signal_init
h) check_startup
6) early-boot
7) boot
8) service
3. 同一个section内的执行顺诉根据脚本中的先后位置决定
4. init.rc 和 init.xxx.rc的执行顺序,两个脚本文件可以包含相同的sction,但是对每一个section,都是先执行完init.rc,再去执行 init.xxx.rc.
8) service
3. 同一个section内的执行顺诉根据脚本中的先后位置决定
4. init.rc 和 init.xxx.rc的执行顺序,两个脚本文件可以包含相同的sction,但是对每一个section,都是先执行完init.rc,再去执行 init.xxx.rc.
具体service启动:
ueventd:代码路径为/system/core/init,启动系统的uevent监听服务进程,通过makefile得知ueventd是软链接到了/init。
console:开启一个 shell,路径/system/bin/sh, 里边包装了cd,ls等这些常规系统指令。
adbd:开启adb-daemon。
servicemanager:大内总管服务进程,掌管系统内一切binder-service。
vold:android的udev,路径/system/vold。
netd:开启netd。
debuggerd:开启debug系统,/system/core/debuggerd。
surfaceflinger:开启surface-server。
zygote:android系统的孵化器进程,开启system_server和javaRuntime。frameworks/base/cmds/app_process。
mediaserver:add AudioFlinger,AudioPolicyService,MediaPlayerService and CameraService to servicemanager,同时启 动管理binder通讯的机制,依靠这两个类来完成binder机制在android中间层所体现的功能:ProcessState 和 IPCThreadState。Code path:frameworks目录下的mediaserver。
bootanimation:开机动画和铃声。/frameworks/base/cmds/bootanimoation。
installed:加载应用的daemon。frameworks/base/cmds/installed。
后续还包括一些无线连接方面的server开启。(BT,WIFI,GPRS等)。
servicemanager:
代码实现路径framworks/base/cmds/servicemanager
此server的主要功能是对系统中所有使用binder机制的service进行管理,而所有使用该机制的service都会去SM注册,SM会相将
已注册过的service加入自己的管理List,对其他service提供的接口有:获取service,查看service是否存在,添加service ,列出
service清单。其中用的最多的就是获取、添加。service间通过binder机制进行交互的时候,首先获取欲交互的service的binder描述
符句柄,类似于linux层面的进程描述符。持有该描述符后,方可通信。
#define BINDER_SERVICE_MANAGER ((void*) 0)
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
// 打开binder设备,mmap映射当前进程的binder接收缓冲区,返回一个binder_state结构体 。
if (binder_become_context_manager(bs)) {
// 通过这个函数将当前进程设置成服务管理进程MSgr,整个系统就这一个。
…
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
/*svcmgr_handler作为处理函数,所能完成的操作有:获取service,查看service是否存在,添加service ,列出service清单。其中用的最多的就是获取、添加。*/
return 0;
}
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
// 打开binder设备,mmap映射当前进程的binder接收缓冲区,返回一个binder_state结构体 。
if (binder_become_context_manager(bs)) {
// 通过这个函数将当前进程设置成服务管理进程MSgr,整个系统就这一个。
…
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
/*svcmgr_handler作为处理函数,所能完成的操作有:获取service,查看service是否存在,添加service ,列出service清单。其中用的最多的就是获取、添加。*/
return 0;
}
zygote:
代码路径frameworks/base/cmds/app_process
该进程被称作Android系统的孵化器进程。是init进程解析玩init.rc之后启动的,可执行程序是system/bin/app_process,调用成功
之后,无耻的改名为zygote,这样我们在控制台用ps查看进程列表的时候就看不到app_process,取而代之的是zygote。
runtime.start()实际调用AndroidRuntime::start(),在这个函数中,会新建并启动一个虚拟机实例来执行
com.android.internal.os.ZygoteInit这个包的main函数。这个main函数中会fork一个子进程来启动systemserver,父进程就作为真正的
孵化进程存在了,每当系统要求执行一个 Android应用程序,Zygote就会收到socket消息FORK出一个子进程来执行该应用程序。因
为Zygote进程是在系统启动时产生的,它会完成虚拟机的初始化,库的加载,预置类库的加载和初始化等操作,而在系统需要一个
新的虚拟机实例时可以快速地制造出一个虚拟机出来。
每一个Android应用都运行在一个Dalvik虚拟机实例里,而每一个虚拟机实例都是一个独立的进程空间。虚拟机的线程机制,内
每一个Android应用都运行在一个Dalvik虚拟机实例里,而每一个虚拟机实例都是一个独立的进程空间。虚拟机的线程机制,内
存分配和管理,Mutex等等都是依赖底层linux实现的。所以android应用程序中创建了线程将会实际调用到linux的线程创建接口,和虚
拟机所在进程共享一个虚拟机实例对java代码执行。
zygote(app_process)----->AndroidRuntime::start()------>startSystemServer(ZygoteInit.java)----->
fork()完成后父进程返回
true,子进程执行RuntimeInit.zygoteInit(parsedArgs.remainingArgs)------>applicationInit------>invokeStaticMain(根据参数提
供的包名,找到system_server的包,并执行其main函数。frameworks/base/cmds/system_server)------>system_init()(init1)--
--->init2() 路径:frameworks/base/services/java/com/android/server------>ServerThread()(其run函数会开启Android的大部
分service,最终进入Loop.loop())
HOME启动在上述的serverthread中,在各个server调用systemready通知系统就绪的流程中,有一个
ActivityManagerService.self().systemReady(),会回调ActivityManagerService.java类当中systemReady()接口,之后是
mMainStack.resumeTopActivityLocked(null)类文件ActivityStack.java,而后mService.startHomeActivityLocked(mCurrentUser)(再次回
调ActivityManagerService.java该接口)----->mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo, null, null, 0, 0, 0, false, false),
在此启动HOME。
至此,Android系统的init启动流程告一段落。