安卓系统启动过程

韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha [email protected]

android启动图示

====

当你按下电源开关后Android设备执行了以下步骤。


此处图片中step2中的一个单词拼写错了,Boot Loaeder应该为Boot Loader

====

第一步:启动电源以及系统启动

当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。

第二步:引导程序

引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redbootubootqi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。

引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。

Android引导程序可以在\bootable\bootloader\legacy\usbloader找到。
传统的加载器包含的个文件,需要在这里说明:

  1. init.s初始化堆栈,清零BBS段,调用main.c的_main()函数;
  2. main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签。

更多关于Android引导程序的可以在这里了解。

第三步:内核

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找到。

对于init.rc文件,Android中有特定的格式以及规则。在Android中,我们叫做Android初始化语言。
Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。
Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。
语法

1

2

3

4

5

; html-script: false ]

on <trigger>

<command>

<command>

<command>

Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。
语法

1

2

3

4

5

; html-script: false ]

service <name> <pathname> [<argument>]*

<option>

<option>

...

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作为应用进程

在这个阶段你可以在设备的屏幕上看到“Android”logo了。

第五步

在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。

Zygote加载进程

  1. 加载ZygoteInit类,源代码:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
  2. registerZygoteSocket()为zygote命令连接注册一个服务器套接字。
  3. preloadClassed “preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在<Android Source>/frameworks/base找到“preloaded-classes”文件。
  4. preloadResources() preloadResources也意味着本地主题、布局以及android.R文件中包含的所有东西都会用这个方法加载。

在这个阶段,你可以看到启动动画。

第六步:系统服务或服务

完成了上面几步之后,运行环境请求Zygote运行系统服务。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以以System Services形式获得。系统服务包含了所有的System Services。

Zygote创建新的进程去启动系统服务。你可以在ZygoteInit类的”startSystemServer”方法中找到源代码。

核心服务:

  1. 启动电源管理器;
  2. 创建Activity管理器;
  3. 启动电话注册;
  4. 启动包管理器;
  5. 设置Activity管理服务为系统进程;
  6. 启动上下文管理器;
  7. 启动系统Context Providers;
  8. 启动电池服务;
  9. 启动定时管理器;
  10. 启动传感服务;
  11. 启动窗口管理器;
  12. 启动蓝牙服务;
  13. 启动挂载服务。

其他服务:

  1. 启动状态栏服务;
  2. 启动硬件服务;
  3. 启动网络状态服务;
  4. 启动网络连接服务;
  5. 启动通知管理器;
  6. 启动设备存储监视服务;
  7. 启动定位管理器;
  8. 启动搜索服务;
  9. 启动剪切板服务;
  10. 启动登记服务;
  11. 启动壁纸服务;
  12. 启动音频服务;
  13. 启动耳机监听;
  14. 启动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孵化器为各进程以写时复制的方式用最小的代价实现了虚拟机。

=======

时间: 2024-10-21 05:21:28

安卓系统启动过程的相关文章

安卓源代码----安卓系统启动过程(初次研究源代码,表述不当还请见谅)

安卓系统事实上是Linux系统中的一个应用程序.相应的程序是app_process,该程序是在init.rc 中被声明的.Linux启动后会启动该zygote(app_process)进程(该程序由java代码实现,由Dalvik虚拟机执行,相应代码在latest-android-2.3.7_r1\android-2.3.7_r1\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java中) 安卓系统中    文件文件夹

安卓源码----安卓系统启动过程(初次研究源码,表述不当还请见谅)

安卓系统其实是Linux系统中的一个应用程序,对应的程序是app_process,该程序是在init.rc 中被声明的,Linux启动后会启动该zygote(app_process)进程(该程序由java代码实现,由Dalvik虚拟机运行,对应代码在latest-android-2.3.7_r1\android-2.3.7_r1\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java中) 安卓系统中    文件目录 安卓

Linux系统启动过程详解

 Linux系统启动过程详解 启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬盘信息.内存信息.时钟信息.PnP特性等等.在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了. 启动第二步--读取MBR众所周知,硬盘上第0磁道第一个扇区被称为MBR,也就是Master Boot Record,即主引导记录,它的大小是512字节,别看地方不大,

魏昊卿——《Linux内核分析》第三周作业:Linux系统启动过程

魏昊卿——<Linux内核分析>第三周作业:Linux系统启动过程 一.实验部分 实验指导 使用实验楼的虚拟机打开shell 1 cd LinuxKernel/ 2 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img 内核启动完成后进入menu程序(<软件工程C编码实践篇>的课程项目),支持三个命令help.version和quit,您也可以添加更多的命令,对选修过<软件工程C编码实践篇>

为什么要有uboot?带你全面分析嵌入式linux系统启动过程中uboot的作用

1.为什么要有uboot 1.1.计算机系统的主要部件 (1)计算机系统就是以CPU为核心来运行的系统.典型的计算机系统有:PC机(台式机+笔记本).嵌入式设备(手机.平板电脑.游戏机).单片机(家用电器像电饭锅.空调) (2)计算机系统的组成部件非常多,不同的计算机系统组成部件也不同.但是所有的计算机系统运行时需要的主要核心部件都是3个东西: CPU + 外部存储器(Flash/硬盘) + 内部存储器(DDR SDRAM/SDRAM/SRAM) 1.2.PC机的启动过程 (1)部署:典型的PC

硬盘分区、寻址和系统启动过程

此文转自CSDN用户 lovingprince  原址:http://www.cnblogs.com/lovingprince/archive/2011/01/05/2166263.html 硬盘物理结构 先看下硬盘物理结构 1 硬盘物理结构 硬盘物理上主要是盘片.机械手臂.磁头.和主轴等组成.在盘片逻辑划分上又分为磁道.扇区,例如下图: 2 盘片磁道.扇区 磁道: 当硬盘盘片旋转时,磁头若保持在一个位置上,则磁头会在盘片表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道.以盘片中心为圆心,由此可以划

Linux基础篇之三系统启动过程

Linux 系统启动过程 Linux系统启动时,我们会看到许多启动信息,其实过程并不复杂,大致可以分为6个阶段: ·内核的引导 ·运行init ·运行级别 ·系统初始化 ·建立终端 ·用户登录系统 内核引导 当计算机打开电源后,首先是BIOS的开机自检,按照BIOS设置第一启动项来启动,默认一般是硬盘启动. 操作系统接管硬件,之后读入/boot目录下的内核文件. 运行init init进程是系统所有进程的起点,是系统所有进程中的父进程,也是系统启动时第一个需要启动的进程.没有这个进程,系统的其他

Android系统启动过程全解析

Android系统是一款基于Linux的移动操作系统,那么Android是如何启动起来的呢?本文就详细阐述Android系统的启动过程. 从内核之上,我们首先应该从文件系统的init开始,因为 init 是内核进入文件系统后第一个运行的程序,通常我们可以在linux的命令行中指定内核第一个调用谁,如果没指定那么内核将会到/sbin/./bin/ 等目录下查找默认的init,如果没有找到那么就报告出错. init.c位置:system/core/init/init.c. 在init.c的main函

Android系统启动过程

Android系统启动过程 首先Android框架架构图:(来自网上,我觉得这张图看起来很清晰) Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用. 启动的过程如下图所示:(图片来自网上,后面有地址)   下面将从Android4.0源码中,和网络达人对此的总结中,对此过程加以学习了解和总结, 以下学习过程中代码片段中均有省略不完整,请参照源码. 一 Init进程的启动 init进程,它是一个由内核启动的用户级进程.内核自行启动(已经被载入内存,开始