Android启动过程

来源:互联网 发布:上海市大数据创新基地 编辑:程序博客网 时间:2024/05/20 10:51

1.  系统的开机综述:

  • 当按下Android设备电源键时究竟发生了什么?
  • Android的启动过程是怎么样的?
  • 什么是Linux内核?
  • 桌面系统linux内核与Android系统linux内核有什么区别?
  • 什么是引导装载程序?
  • 什么是Zygote?
  • 什么是X86以及ARM linux?
  • 什么是init.rc?
  • 什么是系统服务?

当我们想到Android启动过程时,脑海中总是冒出很多疑问。本文将介绍Android的启动过程,希望能帮助你找到上面这些问题的答案。

Android是一个基于Linux的开源操作系统。x86(x86是一系列的基于intel 8086 CPU的计算机微处理器指令集架构)是linux内核部署最常见的系统。然而,所有的Android设备都是运行在ARM处理器(ARM 源自进阶精简指令集机器,源自ARM架构)上,除了英特尔的Xolo设备(http://xolo.in/xolo-x900-features)。Xolo来源自凌动1.6GHz x86处理器。Android设备或者嵌入设备或者基于linux的ARM设备的启动过程与桌面版本相比稍微有些差别。这篇文章中,我将解释Android设备的启动过程。深入linux启动过程是一篇讲桌面linux启动过程的好文。

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

Android启动流程/过程
此处图片中step2中的一个单词拼写错了,Boot Loaeder应该为Boot Loader(多谢@jameslast 提醒)

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

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

第二步:引导程序

引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi 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
on <trigger>
    <command>
    <command>
    <command>

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

1
2
3
4
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”开机启动广播就会发出去。



2. 系统开机流程。

Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。

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

    image


  

  下面将从Android4.0源码中,和网络达人对此的总结中,对此过程加以学习了解和总结,

以下学习过程中代码片段中均有省略不完整,请参照源码。

 

一 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函数中完成:

int do_class_start(int nargs, char **args){    service_for_each_class(args[1], service_start_if_not_disabled);    return 0;}

 

遍历所有名称为classname,状态不为SVC_DISABLED的Service启动

 

复制代码
void service_for_each_class(const char *classname,                            void (*func)(struct service *svc)){       ……}static void service_start_if_not_disabled(struct service *svc){    if (!(svc->flags & SVC_DISABLED)) {        service_start(svc, NULL);    }}
复制代码

 

 

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中:

复制代码
int main(){

     //挂在文件

       //解析配置文件:init.rc……

       //初始化化action queue

     ……       for(;;){              execute_one_command();              restart_processes();              for (i = 0; i < fd_count; i++) {            if (ufds[i].revents == POLLIN) {                if (ufds[i].fd == get_property_set_fd())                    handle_property_set_fd();                else if (ufds[i].fd == get_keychord_fd())                    handle_keychord();                else if (ufds[i].fd == get_signal_fd())                    handle_signal();            }        }       }}
复制代码

 

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

  pid=fork();

  execve();

  在消息循环中:Init进程执行了Android的Command,启动了Android的NativeService,监听Service的变化需求,Signal处理。

Init进程是作为属性服务(Property service),维护这些NativeService。

 

二 ServiceManager启动

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

复制代码
service servicemanager /system/bin/servicemanager  class core  user system  group system  critical  onrestart restart zygote  onrestart restart media  onrestart restart surfaceflinger  onrestart restart drm
复制代码

 

       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的描述

复制代码
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server  class main  socket zygote stream 666  onrestart write /sys/android_power/request_state wake  onrestart write /sys/power/state on  onrestart restart media  onrestart restart netd参数:--zygote --start-system-server
复制代码

 

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

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

复制代码
int main( ){       AppRuntime runtime;       if (zygote) {              runtime.start("com.android.internal.os.ZygoteInit",                startSystemServer ? "start-system-server" : "");       }}class AppRuntime : public AndroidRuntime{};
复制代码

 

(2) 接着到了AndroidRuntime类中:

frameworks\base\core\jni\AndroidRuntime.cpp

复制代码
void start(const char* className, const char* options){       // start the virtual machine Java在虚拟机中运行的       JNIEnv* env;       if (startVm(&mJavaVM, &env) != 0) {              return;       }       //向刚刚新建的虚拟机注册JNI本地接口       if (startReg(env) < 0) {              return;       }    // jni 调用 java 方法,获取对应类的静态main方法    jmethodID startMeth = env->GetStaticMethodID(startClass,         "main","([Ljava/lang/String;)V");       // jni调用 java方法,调用到ZygoteInit类的main函数       jclass startClass = env->FindClass(className);       env->CallStaticVoidMethod(startClass, startMeth, strArray);}
复制代码

 

  到了ZygoteInit.java中的静态main函数中,从C++ ——》JAVA

 

(3)ZygoteInit

       真正Zygote进程:

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

复制代码
public static void main(String argv[]) {       //Registers a server socket for zygote command connections       registerZygoteSocket();       //Loads and initializes commonly used classes and       //used resources that can be shared across processes       preload();       // Do an initial gc to clean up after startup       gc();       if (argv[1].equals("start-system-server")) {              startSystemServer();       }       /**       * Runs the zygote process's select loop. Accepts new connections as       * they happen, and reads commands from connections one spawn-request's       * worth at a time.       */       runSelectLoopMode();    //loop中       /**       * Close and clean up zygote sockets. Called on shutdown and on the       * child's exit path.       */       closeServerSocket();}
复制代码

       Zygote就建立好了,利用Socket通讯,接收请求,Fork应用程序进程,进入Zygote进程服务框架中。

 

四 SystemServer启动

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

复制代码
private static boolean startSystemServer(){       /* Request to fork the system server process 孵化新的进程 */    ZygoteConnection.Arguments parsedArgs = null;       pid = Zygote.forkSystemServer(              parsedArgs.uid, parsedArgs.gid,              parsedArgs.gids,              parsedArgs.debugFlags,              null,              parsedArgs.permittedCapabilities,              parsedArgs.effectiveCapabilities);               /* For child process 对新的子进程设置 */       if (pid == 0) {              handleSystemServerProcess(parsedArgs);       }}void handleSystemServerProcess(parsedArgs){       closeServerSocket();       //"system_server"       Process.setArgV0(parsedArgs.niceName);       //Pass the remaining arguments to SystemServer.    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,      parsedArgs.remainingArgs);       /* should never reach here */}
复制代码

 

(2)RuntimeInit中:

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

复制代码
//The main function called when started through the zygote process.void zygoteInit(int targetSdkVersion, String[] argv){        applicationInit(targetSdkVersion, argv);}void applicationInit(int targetSdkVersion, String[] argv){    // Remaining arguments are passed to the start class's static main    invokeStaticMain(args.startClass, args.startArgs);}void invokeStaticMain(String className, String[] argv){    Class<?> cl;    cl = Class.forName(className);     //获取SystemServer的main方法,抛出MethodAndArgsCaller异常    Method m;    m = cl.getMethod("main", new Class[] { String[].class });    int modifiers = m.getModifiers();    throw new ZygoteInit.MethodAndArgsCaller(m, argv);}
复制代码

 

(3)startSystemServer开始执行并没有去调用SystemServer的任何方法,

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

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

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

       在ZygoteInit的main函数中:

复制代码
public static void main(String argv[]) {       try {              ……              if (argv[1].equals("start-system-server")) {                  startSystemServer();       //这里如果抛出异常,跳过下面流程              }                  runSelectLoopMode();    //loop中              ……       } catch (MethodAndArgsCaller caller) {              caller.run();        //处理的异常       }}
复制代码

 

  如果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

       

复制代码
public static void main(String[] args) {         System.loadLibrary("android_servers");             /*         * This method is called from Zygote to initialize the system.         * This will cause the native services (SurfaceFlinger, AudioFlinger, etc..)         * to be started. After that it will call back         * up into init2() to start the Android services.         */         init1(args);    //native 完了回调init2( )  }//init1:  frameworks/base/services/jni/com_android_server_SystemServer.cpp:: android_server_SystemServer_init1( )   中调用:system_initextern "C" status_t system_init(){       sp<ProcessState> proc(ProcessState::self());       sp<IServiceManager> sm = defaultServiceManager();       //启动SurfaceFlinger 和传感器       property_get("system_init.startsurfaceflinger", propBuf, "1");       SurfaceFlinger::instantiate();       property_get("system_init.startsensorservice", propBuf, "1");       SensorService::instantiate();       // And now start the Android runtime.  We have to do this bit       // of nastiness because the Android runtime initialization requires       // some of the core system services to already be started.    // All other servers should just start the Android runtime at       // the beginning of their processes's main(), before calling       // the init function.       AndroidRuntime* runtime = AndroidRuntime::getRuntime();       //回调 com.android.server.SystemServer init2 方法             JNIEnv* env = runtime->getJNIEnv();       jclass clazz = env->FindClass("com/android/server/SystemServer");       jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");       env->CallStaticVoidMethod(clazz, methodId);           //启动线程池 做为binder 服务       ProcessState::self()->startThreadPool();       IPCThreadState::self()->joinThreadPool();       return NO_ERROR;}
复制代码

 

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( )

复制代码
public static final void init2() {       //建立线程来处理       Thread thr = new ServerThread();             thr.setName("android.server.ServerThread");       thr.start();}//看看线程ServerThread里面都做了什么事情?public void run() {    addBootEvent(new String("Android:SysServerInit_START"));    Looper.prepare();    android.os.Process.setThreadPriority(    android.os.Process.THREAD_PRIORITY_FOREGROUND);    //初始化服务,创建各种服务实例,如:电源、网络、Wifi、蓝牙,USB等,  //初始化完成以后加入到 ServiceManager中,    //事我们用 Context.getSystemService (String name) 才获取到相应的服务    PowerManagerService power = null;    NetworkManagementService networkManagement = null;    WifiP2pService wifiP2p = null;    WindowManagerService wm = null;    BluetoothService bluetooth = null;    UsbService usb = null;    NotificationManagerService notification = null;    StatusBarManagerService statusBar = null;    ……    power = new PowerManagerService();    ServiceManager.addService(Context.POWER_SERVICE, power);    ……    // ActivityManagerService作为ApplicationFramework最重要的服务    ActivityManagerService.setSystemProcess();    ActivityManagerService.installSystemProviders();    ActivityManagerService.self().setWindowManager(wm);     // We now tell the activity manager it is okay to run third party  // code.  It will call back into us once it has gotten to the state  // where third party code can really run (but before it has actually  // started launching the initial applications), for us to complete our  // initialization.  //系统服务初始化准备就绪,通知各个模块    ActivityManagerService.self().systemReady(new Runnable() {           public void run() {                  startSystemUi(contextF);                  batteryF.systemReady();                  networkManagementF.systemReady();                  usbF.systemReady();                  ……                  // It is now okay to let the various system services start their                  // third party code...                  appWidgetF.systemReady(safeMode);                  wallpaperF.systemReady();           }    });    //    //BOOTPROF    addBootEvent(new String("Android:SysServerInit_END"));    Looper.loop();}
复制代码

 

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

  HomeActivity又是如何启动的呢?

  Activity的启动必然和ActivityManagerService有关,我们需要去看看

  ActivityManagerService.systemReady( )中都干了些什么。

 

五 Home界面启动

        

复制代码
 public void systemReady(final Runnable goingCallback) {    ……    //ready callback       if (goingCallback != null)              goingCallback.run();       synchronized (this) {              // Start up initial activity.              // ActivityStack mMainStack;              mMainStack.resumeTopActivityLocked(null);       }……}final boolean resumeTopActivityLocked(ActivityRecord prev) {  // Find the first activity that is not finishing.  ActivityRecord next = topRunningActivityLocked(null);  if (next == null) {    // There are no more activities!  Let's just start up the    // Launcher...    if (mMainStack) {      //ActivityManagerService mService;      return mService.startHomeActivityLocked();    }  }  ……}
复制代码

 

 

 

       然后就启动了Home界面,完成了整个Android启动流程。

      整个过程如下:

  

 


详细参看:

http://blog.csdn.net/lizhiguo0532/article/details/7028910

http://www.cnblogs.com/bastard/archive/2012/08/28/2660389.html



0 0
原创粉丝点击