天天看点

详解Android是如何启动的

android系统启动过程

首先看一张android框架结构图

  

详解Android是如何启动的

linux内核启动之后就到android init进程,进而启动android相关的服务和应用。

启动的过程如下图所示:(图片来自网上,后面有地址)

    

详解Android是如何启动的

一 init进程的启动

  init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行,

并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程。

  启动过程就是代码init.c中main函数执行过程:system\core\init\init.c

在函数中执行了:文件夹建立,挂载,rc文件解析,属性设置,启动服务,执行动作,socket监听……

下面看两个重要的过程:rc文件解析和服务启动。

1 rc文件解析

  .rc文件是android使用的初始化脚本文件 (system/core/init/readme.txt中有描述:

four broad classes of statements which are actions, commands, services,

and options.)

  其中command 就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是 linux 命令,

还有一些是 android 添加的,如:class_start <serviceclass>: 启动服务,class_stop <serviceclass>:关闭服务,等等。

  其中options是针对 service 的选项的。

系统初始化要触发的动作和要启动的服务及其各自属性都在rc脚本文件中定义。 具体看一下启动脚本:\system\core\rootdir\init.rc

       在解析rc脚本文件时,将相应的类型放入各自的list中:

  \system\core\init\init_parser.c  :init_parse_config_file( )存入到

  action_queue、   action_list、 service_list中,解析过程可以看一下parse_config函数,类似状态机形式挺有意思。

  这其中包含了服务:adbd、servicemanager、vold、ril-daemon、debuggerd、surfaceflinger、zygote、media……

2 服务启动

       文件解析完成之后将service放入到service_list中。

文件解析完成之后将service放入到service_list中。

   \system\core\init\builtins.c

       service的启动是在do_class_start函数中完成:

遍历所有名称为classname,状态不为svc_disabled的service启动。

do_class_start对应的命令:

  keyword(class_start, command, 1, do_class_start)

init.rc文件中搜索class_start:class_start main 、class_start core、……

  main、core即为do_class_start参数classname

init.rc文件中service class名称都是main:

       service drm /system/bin/drmserver

    class main

  service surfaceflinger /system/bin/surfaceflinger

       class main

于是就能够通过main名称遍历到所有的service,将其启动。

do_class_start调用:

       init.rc中

    on boot  //action

      class_start core    //执行command 对应 do_class_start

          class_start main

init进程main函数中:

system/core/init/init.c中:

循环调用service_start,将状态svc_restarting启动, 将启动后的service状态设置为svc_running。

  pid=fork();

  execve();

  在消息循环中:init进程执行了android的command,启动了android的nativeservice,监听service的变化需求,signal处理。

init进程是作为属性服务(property service),维护这些nativeservice。

二 servicemanager启动

       在.rc脚本文件中zygote的描述:

   servicemanager用来管理系统中所有的binder service,不管是本地的c++实现的还是java语言实现的都需要

这个进程来统一管理,最主要的管理就是,注册添加服务,获取服务。所有的service使用前都必须先在servicemanager中进行注册。

  do_find_service( )

  do_add_service( )

  svcmgr_handler( )

  代码位置:frameworks\base\cmds\servicemanager\service_manager.c

三 zygote进程的启动

  zygote这个进程是非常重要的一个进程,zygote进程的建立是真正的android运行空间,初始化建立的service都是navtive service.

(1) 在.rc脚本文件中zygote的描述:

代码位置:frameworks/base/cmds/app_process/app_main.cpp

       上面的参数在这里就会用上,决定是否要启动和启动那些进程。

(2) 接着到了androidruntime类中:

frameworks\base\core\jni\androidruntime.cpp

 到了zygoteinit.java中的静态main函数中,从c++ ——》java

(3)zygoteinit

       真正zygote进程:

              frameworks\base\core\java\com\android\internal\os\zygoteinit.java

四 systemserver启动

(1)在zygote进程进入循环之前,调用了startsystemserver( );

(2)runtimeinit中:

       frameworks\base\core\java\com\android\internal\os\runtimeinit.java

(3)从startsystemserver开始执行并没有去调用systemserver的任何方法,

    只是通过反射获取了main方法,付给了methodandargscaller,并抛出了methodandargscaller异常。

    此异常是在哪里处理的呢?

       回到startsystemserver( )函数的调用处:

       在zygoteinit的main函数中:

如果startsystemserver抛出了异常,跳过执行zygoteinit进程的循环,这是怎么回事呢?

  在startsystemserver中异常是由handlesystemserverprocess抛出,而

      pid = zygote.forksystemserver( )

      /* for child process 仅对新的子进程设置 */

      if (pid == 0) {

        handlesystemserverprocess(parsedargs);

      }

      // zygote.forksystemserver根据参数fork 出一个子进程,若成功调用,则返回两次:

    一次返回的是 zygote 进程的 pid ,值大于0;一次返回的是子进程 pid,值等于0否则,出错返回-1;

  caller.run();

    methodandargscaller run函数:调用前面所提到的

    //systemserver main方法

    m = cl.getmethod("main", new class[] { string[].class });

    启动了进程systemserver。

(4)systemserver的执行 init1( )

              //frameworks\base\services\java\com\android\server\systemserver.java

processstate:

  每个进程在使用binder 机制通信时,均需要维护一个processstate 实例来描述当前进程在binder 通信时的binder 状态。

  processstate 有如下2 个主要功能:

  1. 创建一个thread, 该线程负责与内核中的binder 模块进行通信,称该线程为pool thread ;

  2. 为指定的handle 创建一个bpbinder 对象,并管理该进程中所有的bpbinder 对象。

pool thread:

  在binder ipc 中,所有进程均会启动一个thread 来负责与bd 来直接通信,也就是不停的读写bd ,

  这个线程的实现主体是一个ipcthreadstate 对象,下面会介绍这个类型。

  下面是pool thread 的启动方式:

  processstate::self()->startthreadpool();

ipcthreadstate :

  ipcthreadstate 也是以单例模式设计的。由于每个进程只维护了一个processstate 实例,同时processstate 只启动一个pool thread ,

也就是说每一个进程只会启动一个pool thread ,因此每个进程则只需要一个ipcthreadstate 即可。

pool thread 的实际内容则为:

ipcthreadstate::self()->jointhreadpool();

(5)systemserver的执行 init2( )

 到这里系统applicationframework层的xxxservicemanager准备就绪,可以开始跑上层应用了,我们的第一个上层应用homelauncher。

  homeactivity又是如何启动的呢?

  activity的启动必然和activitymanagerservice有关,我们需要去看看

  activitymanagerservice.systemready( )中都干了些什么。

大家可以参考下面的uml图来加深理解:

详解Android是如何启动的

参考文档:

继续阅读