一、系统架构:

一)、系统分层:(由下向上)【如图】

1、安卓系统分为四层,分别是Linux内核层、Libraries层、FrameWork层,以及Applications层;

其中Linux内核层包含了Linux内核和各种驱动;

Libraries层包含各种类库(动态库(也叫共享库)、android运行时库、Dalvik虚拟机),编程语言主要为C或C++

FrameWork层大部分使用java语言编写,是android平台上Java世界的基石

Applications层是应用层,我们在这一层进行开发,使用java语音编写

2、Dalvik VM和传统JVM的区别:

传统的JVM:编写.java文件 à 编译为.class文件 à 打包成.jar文件

Dalvik VM:  编写.java文件 à 编译为.class文件 à 打包成.dex文件 à 打包成.apk文件(通过dx工具)

将所有的类整合到一个文件中,提高了效率。更适合在手机上运行

1、Linux内核层[LINUX KERNEL]:

包含Linux内核和驱动模块(比如USB、Camera、蓝牙等)。

Android2.2(代号Froyo)基于Linux内核2.6版本。

2、Libraries层[LIBRARIES]:

这一层提供动态库(也叫共享库)、android运行时库、Dalvik虚拟机等。

编程语言主要为C或C++,所以可以简单的看成Native层。

3、FrameWork层[APPLICATION FRAMEWORK]:

这一层大部分用java语言编写,它是android平台上Java世界的基石。

4、Applications层[APPLICATION]:应用层

如图所示:

系统分层的图整体简化为下面的一张图,对应如下:

FrameWork层       --------à        Java世界

Libraries层           --------à        Native世界

Linux内核层         --------à        Linux OS

Java世界和Native世界间的通信是通过JNI层

JNI层和Native世界都可以直接调用系统底层

二)、系统编译:

1、主要步骤:系统环境的准备,下载源码、编译源码、输出结果:

目前系统的编译环境只支持Ubuntu 以及 Mac OS 两种操作系统,磁盘的控件要足够大

在下载源码的时候,由于Android源码使用Git进行管理,需要下载一些工具,如apt-get install git-core curl

源码下载好后,进行编译:首先搭建环境,部署JDK(不同的源码编译时需要的JDK版本不同,如2.2需要JDK5,2.3需要1.6),

然后设置编译环境:使用. build/envsetup.sh脚本;选择编译目标(可以根据自己需要的版本进行不同的搭配)

最后通过make –j4的命令进行编译。(make是编译的函数即命令,j4指的是cpu处理器的核数:单核的是j4 x i;双核的是j8)

最后将编译好的结果进行输出:所有的编译产物都位于 /out 目录下

2、编译流程图

二、系统的启动:

通过Linux内核将Linux系统中用户空间的第一个进程init启动起来,这是安卓世界第一个被启动的进程;

然后在init中会加载init.rc的配置文件,并开启系统的守护进程(守护media(多媒体的装载)和孵化器zygote(Java世界的开启)),其实此时调试桥的守护进程也被开启起来了;

然后会处理一些动作执行,在app_main.cpp中会将Zygote孵化器(Zygote是整个java世界的基础,整个安卓世界中(包括framework和app等apk)都是由孵化器启动的)启动起来:

在app_main中,会调用AppRuntime的start方法开启AppRuntime,其实开启的是其父类AndroidRuntime的start方法被调用,zygote由此就被调用了,此时Native层的右上角有一块区域即ANDROID RUNTIME就启动起来了;

与此同时,AppRuntime会调用ZygoteInit的main方法启动ZygoteInit(整个的APPLICATION 和FRAMEWORK都会由ZygoteInit带起来的,JNI也被启动起来):

在ZygoteInit中会调用SystemServer这个类,在SystemServer的main方法中启动init1()方法,将system_init.cpp开启起来,在init1()方法中,将整个Native世界(即LIBRARIES层)开启起来了

然后在system_init.cpp会调用SystemServer的init2()方法开启ServerThread,通过ServerThread将framework层开启起来(所有的就全部开启起来了),即java世界(APPLICATION FRAMEWORK)就被启动了;此时ActivityManager,WindowManager,PackageManager(最主要,所有的清单文件及apk都有它管理)等等framework层全部开启起来

一)安卓系统的总体启动顺序:

1、通过LINUX内核,将init进程启动起来(是Linux系统中用户空间的第一个进程)

2、将ANDROID RUNTIME这一块的内容启动完毕

3、分为两步分别启动LIBRARIES(即Native世界)和APPLICATION FRAMEWORK(即java世界)

1)先启动LIBRARIES(即Native世界)

2)后启动APPLICATION FRAMEWORK(即java世界)【ActivityManager,WindowManager,电源管理等等】

二)具体启动流程

一)、启动流程:

1、init进程:——安卓世界第一个被启动的进程

加载一堆配置文件,核心加载的init.rc配置文件,其中包含了孵化器和守护进程都被开启了

1)、启动服务:开启ServerManager

守护进程启动(Daemon Process):/system/bin/servicemanager

守护的是:

①、Java世界的开启:onrestart  restart  zygote

②、多媒体的装载:onrestart  restart  media

@、adbd的守护也被开启起来了,即调试桥的守护进程也被开启起来了

2)、启动孵化器Zygote

在app_main中启动孵化器Zygote,整个安卓世界中(包括framework和app等apk)都是由孵化器启动的

【此时虚拟机还没开启起来,只是配置了一些vm的参数】

3、app_main:——开启孵化器

app_main中,调用AppRuntime的start方法,将Native层的右上角有一块区域,即ANDROID RUNTIME启动起来

其中的start方法实际是其父类AndroidRuntime的start方法

【此时VM虚拟机被开启起来了,通过start方法开启,在AndroidRuntime中并设置了默认的内存大小16M】

【注册JNI,并启动孵化器Zygote】

4、ZygoteInit开启

AppRuntime被启动后,会调用ZygoteInit的main方法,启动ZygoteInit;

然后,整个的APPLICATION 和FRAMEWORK都会由ZygoteInit带起来的

5、SystemServer启动:

ZygoteInit调用SystemServer这个类,在SystemServer的main方法中启动init1()方法,将system_init.cpp开启起来

在init1()方法中,将整个Native世界开启起来了

6、ServerThread启动(开启framework层)

调用SystemServer的init2()方法开启ServerThread,通过ServerThread将framework层开启起来(所有的就全部开启起来了)

此时ActivityManager,WindowManager,PackageManager(最主要,所有的清单文件及apk都有它管理)等等framework层全部开启起来

 

二)、具体介绍:

1、启动入口:init进程

@、源码位置:/system/core/init/init.c

@、进程入口:main方法

1)创建文件夹,挂载设备【通过mkdir的命令创建,挂载一些系统设备后】

2)重定向输入输出,如错误信息输出【设置了一些输入输出的处理】

3)设置日志输出【一些系统的日志】

4)init.rc系统启动的配置文件【加载了相关的信息,不同版本的手机所特有的配置信息】

①、文件位置:/system/core/rootdir

②、守护进程启动(Daemon Process):/system/bin/servicemanager

守护的是

Java世界的开启:onrestart  restart  zygote

多媒体的装载:onrestart  restart  media

adbd守护也被开启起来了,即调试桥(adb[Android Debug Bridge])的守护进程(adbd[Android Debug Bridge Daemon])也被开启起来了

③、启动Zygote——app_main.cpp【Zygote是整个java世界的基础】

当编译之后,在system/bin/app_process下会有孵化器的启动Xzygote

守护进程被开启之后,紧接着Zygote也被启动起来了

5)解析和当前设备相关的配置信息(/init.%s.rc)

Tips:

当解析完init.rc和设备配置信息后会获取到一系列Action

Init将动作的执行划分为四个阶段(优先级由大到小):

early-init        :初期

Init                :初始化阶段

early-boot       :系统启动的初期

boot               :系统启动

6)处理动作执行:这个阶段Zygote将被启动

7)无限循环阶段,等待一些事情发生

2、Zygote简介:

@、Zygote启动:app_main.cpp

1)Zygote简介:

①、本身为Native的应用程序

②、由init进程通过init.rc加载

2)功能分析:

①、Main方法中AppRuntime.start(),工作由父类AndroidRuntime来完成

②、在AndroidRuntime中开启了如下内容

@startVM——开启虚拟机(查看堆内存设置):默认16M【】

@注册JNI函数【此时还在Native层,需要将连接java和c的桥(即JNI)搭建好】

@启动“com.android.internal.os.ZygoteInit”的main方法

【系统级别的包(由runtime的start方法开启的这个包)】

start方法实际是其父类AndroidRuntime的

@进入java世界的入口

3、ServiceThread的简介:(java世界所做的事情)

1)preloadClasses();:预加载class

读取一个preloaded-classes的配置文件

此文件的内容非常多,这就是安卓系统启动慢的原因之一

此时会有一个垃圾回收的操作gc(),将无用的回收掉

2)ZygoteInit在main方法中利用JNI开启com.android.server.SystemServer

3)启动system_init.cpp处理Native层的服务

4)然后调用SystemServer的init2()

5)启动ServiceThread,启动android服务

6)Launcher启动

三、开机时的时间消耗:

1、ZygoteInit.main()中会预加载类

目录:framework/base/preload-class

ZygoteInit.main()会加载很多的类,将近1800多个(安卓2.3的)

2、开机时会对系统所有的apk进行扫描

需要将所有的应用展现给用户,就需要对apk进行扫描,扫描所有的包

data目录下有个apk的包

system目录下有个apk的包

framework目录下也有相关的包

3、SystemServer创建的那些Service

Android底层有一定的认识,研究过相关的Android源码的更多相关文章

  1. android 2048游戏、kotlin应用、跑马灯、动画源码

    Android精选源码 2048游戏源码 android实现获取号码归属地和其他信息诈骗.骚扰 android kotlin仿开眼app源码 android多种reveal动画效果 android K ...

  2. Android中apk动态载入技术研究(2)android插件化及实现

    了解了android中类载入的前期知识点后,来看看android中DexClassLoader详细的实现     详细载入流程例如以下:     宿主程序会到文件系统比方SD卡中去载入APK[1],然 ...

  3. android WebView详解,常见漏洞详解和安全源码

    这篇博客主要来介绍 WebView 的相关使用方法,常见的几个漏洞,开发中可能遇到的坑和最后解决相应漏洞的源码,以及针对该源码的解析.  转载请注明出处:http://blog.csdn.net/se ...

  4. Android布局优化之ViewStub、include、merge使用与源码分析

    在开发中UI布局是我们都会遇到的问题,随着UI越来越多,布局的重复性.复杂度也会随之增长.Android官方给了几个优化的方法,但是网络上的资料基本上都是对官方资料的翻译,这些资料都特别的简单,经常会 ...

  5. Android动态方式破解apk前奏篇(Eclipse动态调试smail源码)

    一.前言 今天我们开始apk破解的另外一种方式:动态代码调试破解,之前其实已经在一篇文章中说到如何破解apk了: Android中使用静态方式破解Apk  主要采用的是静态方式,步骤也很简单,首先使用 ...

  6. [开源类库/项目] android保存崩溃时的错误信息log至本地【源码+jar包+使用说...

    不知大家是否经常遇到这种情况:自己的项目有时会在没有连接到电脑时发生崩溃,好不容易发现的bug结果连接到电脑时又复现不出来了:又或者自己写的一个功能在开机启动时产生小bug导致崩溃,而刚启动的机器想让 ...

  7. Android仿微信朋友圈,全文收起功能,附源码

    在众多的社交类软件中,朋友圈是必不可少的,可以与好友.同学等分享自己的日常和有意思的事情,在开发社交类App时,朋友圈发表的内容你不可能让他全部显示,全部显示的话用户体验度会非常不好,这时就要用到全文 ...

  8. Android查缺补漏(View篇)--事件分发机制源码分析

    在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...

  9. 【Java深入研究】9、HashMap源码解析(jdk 1.8)

    一.HashMap概述 HashMap是常用的Java集合之一,是基于哈希表的Map接口的实现.与HashTable主要区别为不支持同步和允许null作为key和value.由于HashMap不是线程 ...

随机推荐

  1. #include <algorithm>中sort的一般用法

    1.sort函数的时间复杂度为n*log2(n),执行效率较高. 2.sort函数的形式为sort(first,end,method)//其中第三个参数可选. 3.若为两个参数,则sort的排序默认是 ...

  2. Celery+python+redis异步执行定时任务

    我之前的一篇文章中写了[Celery+django+redis异步执行任务] 博文:http://blog.csdn.net/apple9005/article/details/54236212 你会 ...

  3. netty5入门教程

    1.Netty是什么? 本质:JBoss做的一个Jar包 目的:快速开发高性能.高可靠性的网络服务器和客户端程序 优点:提供异步的.事件驱动的网络应用程序框架和工具 通俗的说:一个好使的处理Socke ...

  4. 为WPF程序添加字体

    很多时候我们开发的程序可能会在多个版本的Windows上运行,比如XP.Win7.Win8. 为了程序美观,现在很多公司会使用WPF作为程序的界面设计. 跨版本的操作的操作系统往往有一些字体上的问题, ...

  5. 【C#/WPF】UI控件的拖拽/拉伸

    需求①:控件拖拽——按住鼠标,可自由拖拽控件. 方法:目前看到的办法有两种. 使用ZoomableCanvas:http://www.cnblogs.com/gnielee/archive/2011/ ...

  6. Log4j 2使用教程<转>

    Log4j 2的好处就不和大家说了,如果你搜了2,说明你对他已经有一定的了解,并且想用它,所以这里直接就上手了. 1. 去官方下载log4j 2,导入jar包,基本上你只需要导入下面两个jar包就可以 ...

  7. 跟我学TCP/IP系列

    最近在微信公众号“java与Android开发专栏”,看到系列文章“跟我学TCP/IP系列”,共7章,文章很赞. 系列文章在CSDN上也有分发,下列出地址以备以后查看(版权问题不转载内容). http ...

  8. 使用Ant编译Hadoop工程报错

    在win7用Ant编译hadoop工程的时候,遇到了一个报错,如下: org.eclipse.core.runtime.CoreException: D:\workspace\hadoop-1.1.2 ...

  9. Ajax类

    ajax.js -------------------------[ajax类]-------------------------- function Ajax(recvType){ var aj=n ...

  10. jQuery EasyUI教程之datagrid应用-2

    二.DataGrid的扩展应用 上一份教程我们创建的一个CRUD应用是使用对话框组件来增加或编辑用户信息.本教程将教你如何创建一个CRUD 数据表格(datagrid). 为了让这些CRUD功能正常工 ...