慕课网 android framework 笔记
二,android系统的启动流程
1, Android有哪些系统进程
2,系统进程如何启动
3,进程启动后做了什么事情
android有哪些系统进程?可以看看init.rc
里面定义了很多service,就是要单独启动的系统服务进程
service zygote /system/bin/app_process
service servicemanager /system/bin/servicemanager
service surfacelinger /system/bin/surfaceflinger
service media /system/bin/mediaserver
还有一个非常关键的系统服务:System server,,它不在init.rc,因为它是zygote创建的,不是init进程创建的,
所以搞定zygote和system server的启动流程就好了
zygote怎么启动?
init进程fork出zyogte进程
启动虚拟机,注册jni函数,为进入java层做准备
预加载系统资源,如系统主题资源,类等
启动system server,非常重要,里面跑了很多系统服务
进入socket Loop,不断接受socket消息并处理
zygote工作流程:
启动的最后,进入了socket loop循环,有消息进入runOnce()函数,如上
boolean runOnce(){
String[] args = readArgumentList(); //读取参数列表
int pid = Zygote.fotkAndSpecialize(); //根据参数启动子进程
if(pid == 0){
//in child
handleChildProc(args, ...);
//在子进程里面干活,其实执行的就是java类得main函数(入口函数),java类名来自上面读取的参数列表。
//参数列表是AMS跨进程发过来的,类名就是ActivityThread.main(),
//也就是说,应用程序进程执行后会马上执行ActivityThread.main()函数
return true;
}
}
system server如何启动
private static boolean startSystemServer(...){
String args[] = {
...
"com.android.servver.SystemServer",
}
int pid = Zygote.forkSystemServer(...); //创建system server进程,zygote fork出来
if(pid == 0){
handleSystemServerProcess(parsedArgs); //子进程,走进system server启动的具体逻辑了
}
return true;
}
void handleSystemServerProcess(Arguments parsedArgs){
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,paresdAegs.remainingArgs,...);
}
//初始化分三步
void zygoteInit(String[] argv, ...){
commonInit();
nativeZygoteInit(); //这步比较重要
applicationInit(argv,...);
}
//nativeZygoteInit(),这里启动了binder机制,binder线程,因为system server里很多系统服务需要和其他进程通信
//如何应用进程通讯,或者和service manager进程通信
virtual void onZygoteInit(){
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
}
3,applicationInit
//调用java类的入口函数,就是system server的java类
void applicationInit(){
invokeStaticMain(args,...);
}
//system servier的类的main函数
public static void main(String[] args){
new SystemServer().run(); //new了一个SystemServer对象,执行了它的run函数
}
private void run(){
Looper.prepareMainLooper(); //为主线程创建Looper
System.loadLibrary("android_servers"); //加载共享库,就是system server里的系统服务的native 层的代码,都在共享库
createSystemContext(); //创建系统上下文,system server可以看成是应用进程,因为它也有context,application,Activity thread
//系统服务分3批次,分别启动
startBootstrapServices();
startCoreServices();
startOtherServices();
//不管这个loop是不是真的在处理消息,但这个主线程不可以退出,主线程退出进程就退出了
Looper.loop();
}
看两个问题:
系统服务如何启动?
怎么解决系统服务之间互相依赖?
系统服务怎么启动?
系统服务怎么发布,让应用程序可见?
系统服务跑在什么线程?
1)系统服务怎么发布?
//就是系统服务把binder注册到ServiceManager里面
void publishBinderService(String name, IBinder service){
publishBinderService(name, service, false);
}
void publishBinderService(String name, IBinder service,...){
ServiceManager.addService(name, service, allowlsolated);
}
2)系统服务跑在什么进程?
1))是主线程吗?没有哪个系统服务用了主线程,主线程什么都没干。
2))工作线程?两种情况
有的服务有自己的工作线程:AMS PMS 还有Package manager service //08:03,PMS还是WMS?
还有大家共用的工作线程:DisplayThread, FgTHread, IoThread, UiThread。
DisplayThread是显示用的
FgThread是前台任务
IoThread是Io任务
UiThread是Ui显示的,UiThread并不是主线程,而是一个子线程,所以说明UI的刷新不必一定在主线程,子线程也行
3))跑在binder线程?
一定的,因为应用跨进程调过来肯定先在binder线程里面
作业:
1),为什么系统服务不都跑在binder线程,
2),为什么系统服务不都跑在自己私有的工作线程?
3),跑在binder线程和跑在工作线程,如何取舍?
答案:
1)binder形成是大家共享的,如果系统负载重,binder线程池忙碌,可能影响系统服务响应的实时性,而且如果任务太耗时,长时间占用binder线程也不好。
2)不可能每个服务都启动工作现场,一共上百个系统服务,线程开太多会内存溢出的,太多线程之间切换对性能不利。
3)如果对实时性要求不高,处理不好使的任务可以放在binder线程。
另外启动工作线程可以避免同步问题,因为AP挂检查调用过来是在binder线程池,通过切到工作线程就可以让binder调用序列化,不用到处上锁。
2,怎么解决系统服务启动的互相依赖
服务A依赖服务B,B依赖C
像system server里,系统服务有7 80个,解决复杂的依赖关系不容易,
1)分批次启动,要启动的service分成三批次,
基础的先启动:AMS PMS PKMS,很多service都依赖于他们所以要先启动
2)分阶段启动,通知已启动的service到了什么阶段,哪些资源可以用了,这些service就可以做这个阶段可以做的初始化了。
桌面的启动
AMS服务就绪时会调用systemReady函数,里面会启动桌面
public void systemReady(final Runnable goingCallback){
...
startHomeActivityLocked(mCurrentUserId, "systemReady");
...
}
桌面可以看成单独的系统级的应用,这里只启动了桌面的Activity,Activity的onCreate里面会启动LoaderTask
mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
//loaderTask会想packageManagerService查询所有当前已经安装的应用,把图标显示到桌面上,点击图标,就会启动应用的LauncherActivity
mPm.queryIntentActivitiesAsUser
回到题目,说说Android系统的启动流程:
简单的说肯定不行:启动zygote , systemserver, 桌面
也不用说的太细,因为涉及太多,一天也说不完,流程说清,主要围绕zygote,systemserver展开,
1)zygote如何启动,启动后做什么事情,最后怎么进入socker looper循环等待创建应用进程的,
2)system server怎么启动,做什么事情,这个进程做什么用的,
3)系统服务怎么启动的,怎么解决相互依赖,怎么发布到service manager的,桌面怎么启动的
技巧点拨,面试技巧
1) 条理清晰,what how why,对于复杂的问题,如果没有一条线穿起来,会很没有条理,
2) 结论 + 细节,是什么后有为什么,证明思考过,有自己的想法和思路
3) 有技巧的转移话题到自己熟悉的领域