当前位置: 移动技术网 > 移动技术>移动开发>Android > Android系统启动概览

Android系统启动概览

2020年07月24日  | 移动技术网移动技术  | 我要评论

入伏第二天,好热。
Android系统架构
早期Android版本系统架构包括4层:
在这里插入图片描述
后续新版本将系统架构增加了 HAL 层,即分为 5层,
在这里插入图片描述
包含:Linux内核层,硬件抽象层(HAL),Android Runtime /Native Lib层,Framework层,系统应用层。
在这里插入图片描述
1.Android是基于Linux内核的系统。
使用Linux内核可避免Android直接与硬件进行交互,且Linux本身也是开源的。
Linux内核为Android提供了线程机制,内存管理机制以及一些关键的安全性能,其中包括:基于用户权限,进程隔离,用
于实现安全IPC的可扩展机制等。
2.HAL(硬件抽象层)
通过定义硬件“驱动”接口,来进一步降低Android系统与硬件之间的耦合度。
3.Android Runtime
ART是Android 4.4引入的一个开发者选项,是Android5.0以及更高的Android版本默认的运行时。
在Android版本5.0之前,Android Runtime是Dalvik , Android版本5.0(api 21)之后 Android Runtime 是ART。Google已不
再继续维护和 提供Dalvik运行时。Dalvik与ART都依赖于Linux内核。
JIT(Just-In-Time) 即时编译 /动态编译,执行时动态编译程序。.java文件经过编译器(Javac)编译成.class文件,之后dx工具解析class文件,合并为多个class文件以生成Dex文件。每个Android应用底层都会对应一个独立的Dalvik虚拟机实例,当Dalvik虚拟机启动并初始化后,Dex文件被映射到当前内存中,解释器开始将Dex文件中的每一条字节码解释为本地代码并执行。当Dalvik虚拟机使用JIT编译方式,则将反复执行的热代码编译成本地码,以此方式避免解释器反复解释每一条字节码为本地代码并执行,JIT提高运行效率。Dalvik虚拟机在运行时, 如果需要调用一个成员方法或者一个成员变量所属的类没有被解析时,虚拟机会调用类加载模块,对这个类,超类以及这些类的相关接口进行加载和连接。
ART(Ahead-Of-Time) 预先编译。ART虚拟机使用AOT编译模式。系统在安装应用时,进行预编译(AOT),将字节码
预先编译成机器码并存在本地,每次运行程序的时,不用重新编译,是真正意义上的本地应用,但是该方式会导致App安装
速度较慢,并占用额外空间。
在Android 7.0之后,Google又引入了JIT编译方式,形成 AOT/JIT 混合编译模式。系统安装应用时,暂不进行AOT,当手机
进入空闲或充电状态下,才会执行AOT操作,当应用安装之后立即运行时,依然使用JIT方式以提高运行效率。
ART相较Dalvik而言,在垃圾回收方面、开发和调试方面均进行了优化。
4.Native C/C++ Libraries 也称为Native层,提供动态库(也叫共享库)。

Android手机开机执行过程简介。
1.当手机处于关机状态下,按下电源键,手机通电,此时硬件电路(PCB板)会产生一个复位时序,保证CPU完成复位之
后,从已知的、固定的地址获取指令执行“引导程序-BootLoader”。
Android系统中的处理器根据其自身内核的架构可分为7种。处理器是一种统称,可以指具体的CPU芯片,比如Intel 8086 处理器。处理器内部一般包含CPU,片上内存,片上外设接口等不同硬件逻辑。处理器内部的中央处理单元缩写为CPU。 在这里插入图片描述
为了减小应用Apk的体积,可以只引用armeabi 版本的.so文件或者只引用armeabi-v7a版本的.so文件或者arm64-v8a版本的.so文件。比如支付宝(版本号10.1.98.7000)仅有armeabi,今日头条(版本7.8.2)仅有armeabi-v7a而微信(版本7.0.16-豌豆荚android应用市场下载)仅有arm64-v8a文件夹。
更多关于Android处理器架构知识,请具体可参考:https://juejin.im/post/5eae6f86e51d454ddb0b3dc6
2.Bootloader执行后,加载Linux内核到手机内存中(RAM),之后创建init进程(pid = 1,Android中第一个被启动的进程 system/core/init/init.cpp)。init进程会读取init.rc文件(system/core/rootdir/init.rc)并执行该文件所列出的命令。
init.rc文件是Android系统重要的配置文件,里面记录了启动系统各组件的动作。
从结构来看,init.rc文件为两级结构:
第一级是 section,分为以下三类:
(1)以on开头的section, 会执行一系列命令。
(2)以service开头的section,指定一个service及相关参数。
(3)以import开头的section.
第二级是针对每个section的动作和参数。
(以上参考《基于android内核与系统架构源码分析》一书)

//system\core\init\init.cpp 文件
int main(int argc,char** argv ){
	......
	//解析init.rc文件。
	init_parse_config_file("/init.rc");
	......
}

//system\core\rootdir\init.rc 文件
	import /init.${ro.zygote}.rc
//而system\core\rootdir\init.zygote*.rc文件。
//zygote 对应的service section 内容如下:
	service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
	class main
 	socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

解析完成之后,zygote进程由init 通过fork创建。其入口函数文件位于frameworks\base\cmds\app_process\app_main.cpp ,并且执行app_main.cpp文件中的main函数( )。

//frameworks\base\cmds\app_process\app_main.cpp
//启动zygote时来自init.rc中的设置参数 -Xzygote/system/bin --zygote --start-system-server
int main(int argc,char* const argv[]){
	......
	//创建AppRuntime 对象
	AppRuntime runtime(argv[0] , computeArgBlockSize(argc,argv));
	//调用start 启动zygoteInit
	runtime.start("com.android.internal.os.ZygoteInit",args,true);
}

AppRuntime 类的声明和实现均在app_main.cpp中,它是从AndroidRuntime类派生出来的。查看源码分析runtime.start()方法实际是调用了AndroidRuntime.start()。

//frameworks\base\core\jni\AndroidRuntime.cpp
void AndroidRuntime : start(const char* className,const Vector<String8>& options,bool zygote){
	//className即 com.android.internal.os.ZygoteInit , zygote 的值为true
	......
	//创建虚拟机
	if(startVm(&mJavaVM,&env,zygote) !=0){
		return;
	}
	onVmCreated(env);
	......
	//注册JNI方法
	if(startReg(env)<0){
		return;
	}
	//如果className包含 "\" 更换为"."
	char* slashClassName = toSlashClassName(className);
	//找到 ZygoteInit类
	jclass startClass = env->FindClass(slashClassName);
	//找到ZygoteInit的main方法
	jmethodID startMeth = env->GetStaticMethodId(startClass,"main","([Ljava/lang/String;)V");
	//通过JNI调用main方法
	env->CallStaticVoidMethod(startClass,startMeth,strArray);	
}

至此,虚拟机已创建,JNI函数已注册。接下来进入java世界。ZygoteInit类很关键,通过执行该类中的main()函数,完成了整个Java世界的创建。

//ZygoteInit.main()
public static void main(String argv[]){
	//1.注册zygote socket 
	String socketName = "zygote"
	registerZygoteSocket(socketName);
	//2.预加载类和资源 preLoad()
	preloadClasses();
	preloadResources();
	//3启动SystemServer
	startSystemServer(abiList,socketName);
	//4.启动Loop来处理AMS
	runSelectLoop(abilist);
}

1.zygote 与系统中其他程序的通信没有使用Binder,而是采用Socket。registerZygoteSocket()方法执行后,即创建一个LocalServerSocket并作为服务端等待AMS请求zygote 进程来创建一个新的应用进程。
2.preloadClasses() 函数通常执行时间较长,是导致Android系统启动慢的原因之一。preLoadResources() ,它主要是加载framework-res.apk中的资源。
3.从zygote进程fork一个子进程即 system_server进程。

  int pid  = Zygote.forkSystemServer(parsedArgs.uid,parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);

4.通过registerServerSocket()创建的服务端socket, 可用在runSelectLoop()函数中。随时接收AMS发送过来的请求以便创建应用进程。

SystemServer 启动
SystemServer 是Zygote进程首个创建出来的进程,创建完成之后,ZygoteInit会执行 handleSystemServerProcess()函数。
接下来回依次执行:
1.ZygoteInit.nativeZygoteInit(); //native层的初始化 nativeZygoteInit()为一个native函数,位于AndroidRuntime.cpp中,由于AppRuntime继承于AndroidRuntime, 可以查到 nativeZygoteInit()函数在AppRuntime中实现(app_main.cpp中),执行完之后,启动了Binder线程池
2.随后,通过反射进入到SystemServer.main()函数中,主要功能:
a.初始化系统Context.
b.创建SystemServiceManager ,他会对系统的Service进行管理(启动,创建等),比如创建AMS,PMS。
Zygote 分裂出的SystemServer进程用于创建Android系统中的核心服务。
Launcher启动
ActivityManagerService是在SystemServer.startBootstrapServices()函数中创建的,创建完成之后,会调用SystemServer.startOtherService()函数,其中会执行
ActivityManagerService.systemReady()方法。

//ActivityManagerService
public void systemReady(Runnable goingCallback){
	......
	//start up inital activity 
	startHomeActivityLocked(mCurrentUserId,"systemReady");
	......
}
boolean startHomeActivityLocked(int userId, String reason) {
	Intent intent = getHomeIntent();
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
       ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instrumentationClass == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                mStackSupervisor.startHomeActivity(intent, aInfo, reason);
            }
        }

        return true;
}

通过 mStackSupervisor.startHomeActivity(intent, aInfo, reason); 最终启动Laucher

本文地址:https://blog.csdn.net/yuanhouhuohe/article/details/107419570

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网