亦余心之所善兮,虽九死其犹未悔。这篇文章主要讲述安卓系统启动过程相关的知识,希望能为你提供帮助。
韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com
android启动图示
文章图片
====
当你按下电源开关后Android设备执行了以下步骤。
文章图片
此处图片中step2中的一个单词拼写错了,Boot Loaeder应该为Boot Loader
====
第一步:启动电源以及系统启动
当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。
第二步:引导程序
引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。
引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。
Android引导程序可以在
\\bootable\\bootloader\\legacy\\usbloader
找到。传统的加载器包含的个文件,需要在这里说明:
- init.s初始化堆栈,清零BBS段,调用main.c的_main()函数;
- main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签。
第三步:内核
Android内核与桌面linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。
第四步:init进程
init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。
- init进程可以在
/system/core/init
找到。 - init.rc文件可以在
/system/core/rootdir/init.rc
找到。 - readme.txt可以在
/system/core/init/readme.txt
找到。
Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。
Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。
语法
1 2 3 4 5 | ; html-script: false ] on & lt; trigger& gt; & lt; command& gt; & lt; command& gt; & lt; command& gt; |
Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。
语法
1 2 3 4 5 | ; html-script: false ] service & lt; name& gt; & lt; pathname& gt; [& lt; argument& gt; ]* & lt; option& gt; & lt; option& gt; ... |
Options(选项)
选项是对服务的描述。它们影响init进程如何以及何时启动服务。
咱们来看看默认的init.rc文件。这里我只列出了主要的事件以及服务。
Table
Action/Service | 描述 |
on early-init | 设置init进程以及它创建的子进程的优先级,设置init进程的安全环境 |
on init | 设置全局环境,为cpu accounting创建cgroup(资源控制)挂载点 |
on fs | 挂载mtd分区 |
on post-fs | 改变系统目录的访问权限 |
on post-fs-data | 改变/data目录以及它的子目录的访问权限 |
on boot | 基本网络的初始化,内存管理等等 |
service servicemanager | 启动系统管理器管理所有的本地服务,比如位置、音频、Shared preference等等… |
service zygote | 启动zygote作为应用进程 |
第五步
在java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。
Zygote加载进程
- 加载ZygoteInit类,源代码:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
- registerZygoteSocket()为zygote命令连接注册一个服务器套接字。
- preloadClassed “preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在< Android Source> /frameworks/base找到“preloaded-classes”文件。
- preloadResources() preloadResources也意味着本地主题、布局以及android.R文件中包含的所有东西都会用这个方法加载。
第六步:系统服务或服务
完成了上面几步之后,运行环境请求Zygote运行系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以以System Services形式获得。系统服务包含了所有的System Services。
Zygote创建新的进程去启动系统服务。你可以在ZygoteInit类的”startSystemServer”方法中找到源代码。
核心服务:
- 启动电源管理器;
- 创建Activity管理器;
- 启动电话注册;
- 启动包管理器;
- 设置Activity管理服务为系统进程;
- 启动上下文管理器;
- 启动系统Context Providers;
- 启动电池服务;
- 启动定时管理器;
- 启动传感服务;
- 启动窗口管理器;
- 启动蓝牙服务;
- 启动挂载服务。
- 启动状态栏服务;
- 启动硬件服务;
- 启动网络状态服务;
- 启动网络连接服务;
- 启动通知管理器;
- 启动设备存储监视服务;
- 启动定位管理器;
- 启动搜索服务;
- 启动剪切板服务;
- 启动登记服务;
- 启动壁纸服务;
- 启动音频服务;
- 启动耳机监听;
- 启动AdbSettingsObserver(处理adb命令)。
一旦系统服务在内存中跑起来了,Android就完成了引导过程。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。
========
文章图片
Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。
启动的过程如下图所示
文章图片
Android系统启动过程
=========
Android的启动过程可以分为两个阶段,第一阶段是Linux的启动,第二阶段才是Android的启动,下面我们分别来了解一下具体的过程。
首先是Linux启动,这一部分我想就可以略过了,无非是Linux的Bootloader,Kernel,Driver之类的,在这里唯一要提到 的就是ServiceManager,即服务管理器,这个是做为一个进程在Android加载之前就被启动了,我们可以从init.rc中看到这个配置 项:
service servicemanager /system/bin/servicemanager
ServiceManager是Binder的服务管理守护进程,是Binder的核心,由其使用Binder驱动进行IPC管理,关于IPC通讯 的机制,此处不再详述。在APP和Framework中,应用程序使用的ServiceManager.java就是通过Proxy与这个守护进程进行的 通讯。
然后是Android的启动,接下来要详细描述的部分。我们还是先看一下init.rc中的配置
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
即linux启动以后,启动zygote服务进程,这个进程恰如其名:孵化器,是所有Android应用程序的孵化器。
我们来看一下app_process的代码,位置是在:
frameworks/base/cmds/app_process/app_main.cpp
在main()函数中有如下代码:
if (0 == strcmp("--zygote", arg)) { bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false; setArgv0(argv0, "zygote"); set_process_name("zygote"); runtime.start("com.android.internal.os.ZygoteInit", startSystemServer); }
从中可以追踪到AndroidRuntime,代码位于:
frameworks/base/core/jni/AndroidRuntime.cpp
在start()函数中有如下代码:
/* start the virtual machine */ if (startVm(& mJavaVM, & env) != 0) goto bail; …… env-> CallStaticVoidMethod(startClass, startMeth, strArray);
即先启动了虚拟机,然后利用JNI调用了zygoteInit函数。
继续追踪到frameworks/base/core/java/com/android/internal/os/ZygoteInit.java的main()函数,代码如下:
if (argv[1].equals("true")) { startSystemServer(); } else if (!argv[1].equals("false")) { throw new RuntimeException(argv[0] + USAGE_STRING); }Log.i(TAG, "Accepting command socket connections"); if (ZYGOTE_FORK_MODE) { runForkMode(); } else { runSelectLoopMode(); }
前一部分是在启动系统服务,后一部分是虽然是一个条件判断,但ZYGOTE_FORK_MODE被赋了false,所以进行else分支的 runSelectLoopMode()函数,在该函数中,实际上是在一死循环中利用zygoteConnection类通过socket的方式进行消息 处理,用于fork出新的zygote,从而以最轻量级的方式实现每个进程一个虚拟机的机制。
继续来看startSystemServer(),代码位于:
frameworks/base/services/java/com/android/server/systemserver.java
在其main()函数中调用了init1(args)这个native函数,利用JNI机制,跟踪至
frameworks/base/services/jni/com_android_server_systemService.cpp,然后到
frameworks/base/cmds/system_server/library/system_init.cpp
在system_init()函数中有如下代码
if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } AndroidRuntime* runtime = AndroidRuntime::getRuntime(); LOGI("System server: starting Android services./n"); runtime-> callStatic("com/android/server/SystemServer", "init2");
即完成了SurfaceFlinger的实例化,然后利用运行时的callStatic()函数调用了SystemServer的init2()函数,这个函数位于:
frameworks/base/services/java/com/android/server/SystemServer.java
代码是:
public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); }
在这个ServerThread线程中,可以看到我们熟悉的Android服务了,比如WallpaperService服务的启动:
try { Slog.i(TAG, "Wallpaper Service"); wallpaper = new WallpaperManagerService(context); ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper); } catch (Throwable e) { Slog.e(TAG, "Failure starting Wallpaper Service", e); }
最后,调用各服务的systemReady()函数通知系统就绪。
至此,系统的启动过程结束
从这里可以看出,linux的init在启动若干守护进程之后,就启动了Android的runtime和zygote,zygote再启动虚拟机,系统 服务,系统服务再启动完本地服务后,又启动了若干Android服务,并完成向ServiceManager的注册工作,最后系统启动完成。系统的进程空 间如下图所示:
可见,由zygote孵化器为各进程以写时复制的方式用最小的代价实现了虚拟机。
至此,系统的启动过程结束,借用两张图来说明问题:
文章图片
从这里可以看出,linux的init在启动若干守护进程之后,就启动了Android的runtime和zygote,zygote再启动虚拟机,系统服务,系统服务再启动完本地服务后,又启动了若干Android服务,并完成向ServiceManager的注册工作,最后系统启动完成。系统的进程空间如下图所示:
可见,由zygote孵化器为各进程以写时复制的方式用最小的代价实现了虚拟机。
文章图片
=======
推荐阅读
- android中canvas的clipRect和concate调用顺序不同导致的图像效果不同。
- android 内存分哪些区
- App phonegap
- ionic3 app 退出应用程序
- React Native运行安卓报错解决记录
- [Android]_[0基础]_[adb 有用命令]
- 安卓 应用app启动过程
- win7下react-native安卓打包踩坑
- android开发学习之路——连连看之游戏逻辑