Android(安卓)内核剖析
16lz
2021-12-04
Android 操作系统 是基于Linux实现的,然而Android的核心价值却不是Linux,所以说,Android的内核不是指Linux,本书不是一本介绍Linux的书。这就好比苹果的操作系统iOS是基于Unix实现的,然而iOS的核心价值却不是Unix。 那么,Android的内核是什么,它的核心价值都包含什么? 大家听过和Android内核最多的词语应该是“Android Framework”以及“Dalvik虚拟机”,那么,这两个核心部分从内部运行机制的角度来看,到底扮演着什么角色,彼此之间如何协同工作呢?了解清楚了这些,也就了解了所谓Android的核心价值,即Android内核。 从进程的角度来看,Android的运行环境如下图所示: 当 Linux内核 启动后,此时系统的状态和普通的Linux系统基本相同,通过配置Linux中的init.rc文件,可以指定内核启动后都要执行什么程序,而这之后所启动的程序才是Android系统和普通Linux应用系统的区别。
init.rc中所启动的一个重要进程被称作zygote进程,如上图中 红色边框 所示,zygote这个英文单词的意思是“受精卵”,本书将其称为“种子进程”,从进程的角度来看,种子进程仅仅是一个Linux进程而已,它和一个只包含main()函数的C程序所产生的进程是同一个级别,如上图中 双实线 边框所示。 种子进程里面所运行的程序基本上就是Android内核的精华所在,其内部主要完成了两件事情。第一件事情是装载了一段程序代码,这些代码都是用C语言写的,这段代码的作用只是为了能够执行Java 编译器 编译出的字节码,这段代码就是传说中的Java虚拟机,在Android中称为Dalvik虚拟机。 第二件事情必须基于第一件事情之后,即当Dalvik虚拟机代码初始化完成后,从一个名为ZygoteInit.java类中的main()函数中开始执行。这里大家就奇怪了,Dalvik虚拟机如何知道ZygoteInit这个Java类在哪个Jar包里面?实际上,这个Jar包的目录位置信息正是在init.rc中进行配置的,只不过没有直接指定,而是使用一个标志符,当这个标志符是“zygote”时,Dalvik虚拟机就会从“硬编码”的字符串中得到ZygoteInit类所在的Jar包,而这个Jar包正是framework.jar。 接下来的事情即是简单的,又是复杂的。所谓简单是指,ZygoteInit类中main()函数所做的事情和Linux本身就没多大关系了,理论上完全可以在该main()函数中实现任意简单的功能;所谓复杂是指,该main()函数中才刚刚开始启动Android的核心功能。 在ZygoteInit类中的main()函数中,首先加载一些类文件,这些类将作为以后所有其它Apk程序共享的类,接着,会创建一个Socket服务端,该服务端将用于通过Socket启动新进程。 该进程之所以被称为“种子”进程的原因就是,当其内部的Socket服务端收到启动新的Apk进程的请求时,会使用Linux的一个系统调用folk()函数从自身复制出一个新的进程,新进程和Zygote进程将共享已经装载的类,这些类都是在framework.jar中定义的。 以上从进程的角度分析了Android内核的概念,下面从 图形用户界面 的角度再来看看Android内核的含义。大家都知道,Linux内核所提供的功能主要包括: l 进程调度 l 内存管理 l 驱动模型 这些功能都是和用户界面没有关系的,内核一般仅仅会通过USB接口或者RS232串口输出一些状态信息,而对于窗口操作系统而言,这还远远不够,最重要的就是操作系统应该提供一套用户界面子系统,该子系统包含如何创建、删除窗口,以及用户如何和窗口进行交互,同时还应该提供一套界面程序库,以便第三方开发商能够基于该界面库快速的开发一些窗口 应用程序 。而这就是Android最核心的内容,完成这些功能的代码大部分都在那个framework.jar文件中,Dalvik虚拟机只不过是执行这些功能代码的一个环境而已。
init.rc中所启动的一个重要进程被称作zygote进程,如上图中 红色边框 所示,zygote这个英文单词的意思是“受精卵”,本书将其称为“种子进程”,从进程的角度来看,种子进程仅仅是一个Linux进程而已,它和一个只包含main()函数的C程序所产生的进程是同一个级别,如上图中 双实线 边框所示。 种子进程里面所运行的程序基本上就是Android内核的精华所在,其内部主要完成了两件事情。第一件事情是装载了一段程序代码,这些代码都是用C语言写的,这段代码的作用只是为了能够执行Java 编译器 编译出的字节码,这段代码就是传说中的Java虚拟机,在Android中称为Dalvik虚拟机。 第二件事情必须基于第一件事情之后,即当Dalvik虚拟机代码初始化完成后,从一个名为ZygoteInit.java类中的main()函数中开始执行。这里大家就奇怪了,Dalvik虚拟机如何知道ZygoteInit这个Java类在哪个Jar包里面?实际上,这个Jar包的目录位置信息正是在init.rc中进行配置的,只不过没有直接指定,而是使用一个标志符,当这个标志符是“zygote”时,Dalvik虚拟机就会从“硬编码”的字符串中得到ZygoteInit类所在的Jar包,而这个Jar包正是framework.jar。 接下来的事情即是简单的,又是复杂的。所谓简单是指,ZygoteInit类中main()函数所做的事情和Linux本身就没多大关系了,理论上完全可以在该main()函数中实现任意简单的功能;所谓复杂是指,该main()函数中才刚刚开始启动Android的核心功能。 在ZygoteInit类中的main()函数中,首先加载一些类文件,这些类将作为以后所有其它Apk程序共享的类,接着,会创建一个Socket服务端,该服务端将用于通过Socket启动新进程。 该进程之所以被称为“种子”进程的原因就是,当其内部的Socket服务端收到启动新的Apk进程的请求时,会使用Linux的一个系统调用folk()函数从自身复制出一个新的进程,新进程和Zygote进程将共享已经装载的类,这些类都是在framework.jar中定义的。 以上从进程的角度分析了Android内核的概念,下面从 图形用户界面 的角度再来看看Android内核的含义。大家都知道,Linux内核所提供的功能主要包括: l 进程调度 l 内存管理 l 驱动模型 这些功能都是和用户界面没有关系的,内核一般仅仅会通过USB接口或者RS232串口输出一些状态信息,而对于窗口操作系统而言,这还远远不够,最重要的就是操作系统应该提供一套用户界面子系统,该子系统包含如何创建、删除窗口,以及用户如何和窗口进行交互,同时还应该提供一套界面程序库,以便第三方开发商能够基于该界面库快速的开发一些窗口 应用程序 。而这就是Android最核心的内容,完成这些功能的代码大部分都在那个framework.jar文件中,Dalvik虚拟机只不过是执行这些功能代码的一个环境而已。
因此,如果考虑图形用户界面,则一个Android应用程序的内部关系如下图所示:
更多相关文章
- Android电话拨打流程源码分析
- Android(安卓)Linux 内核介绍
- Android跨进程通信方式(IPC)解析
- Android进程与线程基本知识
- 浅析Android单线程模型
- 开发可统计单词个数的Android驱动程序(1)
- Android电话拨打流程源码分析
- 学习01:Android(安卓)4.0_你必须知道的13点
- 【专题】Android(安卓)启动流程相关