Framework面试二:说说Android系统的启动流程

目录

参考文章:

这道题想考察什么?

Android有哪些主要的系统进程?这些进程各自有什么作用?

zygote是怎么启动的?

 SystemServer是怎么启动的?

系统服务是怎么启动的?

系统服务怎么发布,让应用程序可见?

系统服务跑在什么线程?

课堂作业:

怎么解决系统服务之间的互相依赖?

桌面的启动:

总结:


参考文章:

Android系统架构与系统源码目录

Android系统启动流程(一)解析init进程启动过程

Android系统启动流程(二)解析Zygote进程启动过程

以上三篇文章涉及到C语言源码,比较难懂。

这道题想考察什么?

  • Android有哪些主要的系统进程?这些进程各自有什么作用?
  • 这些系统进程是怎么启动的?
  • 进程启动之后主要做了什么事情?

Android有哪些主要的系统进程?这些进程各自有什么作用?

在Android源码的init.rc文件中:

service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm

...

service surfaceflinger /system/bin/surfaceflinger
    class main
    user system
    group graphics
    onrestart restart zygote

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

...

init进程创建的系统进程:zygote、servicemanager、surfaceflinger、mediaserver等

zygote进程创建的系统进程:SystemServer

系统进程有很多,我们只需要关注Zygote和SystemServer就可以了。

zygote是怎么启动的?

Android系统启动流程(二)解析Zygote进程启动过程

以上文章得出的结论:

1.创建AppRuntime并调用其start方法,启动Zygote进程。
2.创建DVM并为DVM注册JNI.
3.通过JNI调用ZygoteInit的main函数进入Zygote的Java框架层。
4.通过registerZygoteSocket函数创建服务端Socket,并通过runSelectLoop函数等待ActivityManagerService的请求来创建新的应用程序进程。
5.启动SystemServer进程。

视频得出的结论:

  • init进程fork出Zygote进程
  • 启动虚拟机,注册JNI函数
  • 预加载系统资源
  • 启动SystemServer
  • 进入Socket Loop

接下来看Zygote的工作流程:

在启动流程的最后一步,Zygote进入了一个loop循环,在这个循环里面,它一方面看有没有发过来socket消息,有消息的话就会执行如下的runOnce函数:

boolean runOnce(){
	//readArgumentList() 读取发过来的参数列表
	String[] args = readArgumentList();

    //创建子线程 该函数返回两次,一次从父进程返回,一次从子进程返回
	int pid = Zygote.forkAndSpecialize(...);

	if(pid == 0){
        //从子进程返回  这里其实就是调用ActivityThread.Main方法
		handleChildProc(parsedArge, ...);

		//should never get here,the child is expected to either
		//throw ZygoteInit.MethodAndArgsCaller or exec().
		return true
	}else{
         //从父进程返回  
		return handleParentProc(pid, ...);
	}

}

 SystemServer是怎么启动的?

Android系统启动流程(三)解析SyetemServer进程启动过程

我们看这个函数:

private static boolean startSystemServer(...){
	String args[] = {
		...
		"com.android.server.SystemServer",
	}

    //通过Zygote.forkSystemServer 创建一个系统进程
	int pid = Zygote.forkSystemServer(...);

	if(pid == 0){
        //SystemServer启动的具体逻辑
		handleSystemServerProcess(parseArgs);
	}

	return true;
}


void handleSystemServerProcess(Arguments parsedArgs){
	RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
		parsedArgs.remainingArgs, ...);
}

void zygoteInit(String[] argv,...){
	//常规的一些初始化
	commonInit();
	//见下面的onZygoteInit函数
	nativeZygoteInit();
	//见下面的applicationInit函数
	applicationInit(argv, ...);
}

//启动binder机制,并且启动一个binder线程
virtual void onZygoteInit(){
	sp<ProcessState> proc = ProcessState::self();
	proc -> startThreadPool();
}

//调用Java类的入口函数,这个Java类其实就是SystemServer类
void applicationInit(...){
	invokeStaticMain(args, ...);
}

//我们来看SystemServer类的入口函数
public static void main(String[] args){
	//看下面的 run方法
	new SystemServer().run();
}

private void run(){
	Looper.prepareMainLooper();

	System.loadLibrary("android_servers");
	createSystemContext();

	startBootstrapServices();
	startCoreServices();
	startOtherServices();

	Looper.loop();

}

SyetemServer在启动时做了如下工作:

  • 1.启动Binder线程池,这样就可以与其他进程进行通信。
  • 2.创建SystemServiceManager用于对系统的服务进行创建、启动和生命周期管理。
  • 3.启动各种系统服务。 

 看两个问题

系统服务是怎么启动的?

系统服务怎么发布,让应用程序可见?

void publishBinderService(String name, IBinder service){
	publishBinderService(name, service, false);
}

void publishBinderService(String name, IBinder service, ...){
	ServiceManager.addService(name, service, allowlsolated);
}

如上,可以看到,最终还是把系统服务 的binder注册到了ServiceManager中

系统服务跑在什么线程?

主线程? 没有看到有哪个系统服务用到了主线程

工作线程? 
工作线程分两种情况:
有的服务有自己独有的工作线程:例如AMS、PMS、PackageManagerService,
还有一些是大家共用的一些线程,比如:DisplayThread(负责显示)  FgThread(负责前台任务) IoThread(负责IO任务) UiThread(负责UI显示,这个需要格外关注,一般我们认为UiThread是主线程,可是从这里看出,它只是一个工作线程,因此充分说明UI的刷新不一定是要在主线程,在子线程也可以)

binder线程? 是在这个线程,因为应用跨进程调过来的时候,肯定首先就是binder线程里面

课堂作业:

  • 为什么系统服务不都跑在binder线程里呢?
  • 为什么系统服务不都跑在自己私有的工作线程里呢?
  • 跑在binder线程和跑在自己私有的工作线程,怎么取舍?

怎么解决系统服务之间的互相依赖?

举例:服务A需要用到服务B的东西,而B有需要用到服务C的东西,这样就形成了一个依赖关系
在SystemServer中,系统服务大概有七八十个。要解决这些服务之间的互相依赖关系,不是一件简单的事情,
那么Android是怎么解决这个问题的呢?

  • 1、分批启动:分为三批:比较基础的服务就先启动:例如AMS PMS PKMS,而一些上层的服务就晚些启动
  • 2、分阶段启动:阶段1、阶段2、阶段3、...

系统服务启动完成以后,就到了桌面的启动了

桌面的启动:

在AMS服务就绪的时候会调用 systemReady函数:

public void systemReady(final Runnable goingCallback){
	...
	//可以把桌面看做一个单独的系统级应用
	//该函数启动一个Activity,就是LauncherActivity
	startHomeActivityLocked(mCurrentUserId, "systemReady");
	...
}

//LauncherActivity的onCreate方法中
mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);

//这个mLoaderTask会向Package Manager Service查询所有当前已经安装的应用,
//然后把其以图标的形式显示在桌面上,当我们点击这个图标的时候,就会启用对应的LauncherActivity
mPm.queryIntentActivitiesAsUser

总结:

说说Android系统的启动流程?

这个问题该怎么回答?

对于该问题的回答,重点在于细节。如果只回答:先启动Zygote、在启动SystemServer、最后启动桌面。这样显然太简单,是不行的。主要围绕Zygote和SystemServer的启动流程来说就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值