ANDROID系统启动流程分析

时间:2021-02-07 04:35:24

Android系统的本地部分启动流程可以分为以下的几个步骤:

(1)BootLoader运行(Linux通用内容,如U-Boot的启动);

(2)Linux内核运行(Linux通用内容,通常是二进制机器代码形式存在);

(3)内核加载根文件系统(Linux通用内容:如从Flash中加载);

(4)init进程运行(用户空间的第一个进程);

(5)运行init.rc脚本;

(6)加载system和data文件系统;

(7)运行各种服务(主要为各个守护进程);


了解Android系统启动流程需要关注以下几个方面:

(1)系统总体的结构(如几个单独的映像);

(2)各个具体程序的组成部分(如可执行程序和配置内容);

(3)系统的运行时结构(如分成若干个进程);

(4)启动流程中系统控制权的转移;

 

一、启动流程介绍

 

1. 硬件启动流程

ANDROID系统启动流程分析

 

       由图可知,系统开机时按照确定的复位时序启动,然后执行bootloader,进入内核初始化操作,当内核初始化完

毕后,便运行linux的第一个应用程序,即android系统的init。

 

2. android init 流程分析

ANDROID系统启动流程分析

 

 

        Init流程的关键点在于分析*.rc文件,这个*.rcandroid的启动脚本,其定义了android待执行的一些命令及相关

service。解析完该文件后,init把待执行的相关命令添加到执行队列,这样在init的轮询过程中,依次执行这些命令。

Init的轮询过程就是启动所有执行队列里command,重启所有需要重启的service,同时启动一个socket用于接收用户对

属性的设置请求,最后接收service终止信号,根据service属性选择重启service或资源回收。

 

3. Zygote分析

       查看zygoteinit.rc的启动参数

        servicezygote /system/bin/app_process -Xzygote /system/bin --zygote--start-system-server

            class main

            socket zygotestream 666

 

        Zygote函数原型在app_main.cpp里,通过main函数传递相关参数。阅读main函数代码,发现其最后调用  

       AppRuntimestart来启动javaZygoteInit

        runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ?"start-system-server" : "");

       start函数有以下三个功能:

       (1)调用startVm创建java虚拟机。

       (2)调用startReg注册JNI函数。

       (3)找到ZygoteInit类,并通过JNI,调用该类的main函数,该函数如下:

 

                   public staticvoid main(String argv[]) {

                       try {

                           // Start profiling the zygoteinitialization.

                           SamplingProfilerIntegration.start();

 

                           registerZygoteSocket();

                           EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,

                           SystemClock.uptimeMillis());

                           preload();

                           EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,

                           SystemClock.uptimeMillis());

 

                           // Finish profiling the zygoteinitialization.

                           SamplingProfilerIntegration.writeZygoteSnapshot();

 

                           // Do an initial gc to clean upafter startup

                           gc();

 

                           // If requested, start systemserver directly from Zygote

                           if (argv.length != 2) {

                               throw newRuntimeException(argv[0] + USAGE_STRING);

                           }

 

                           if(argv[1].equals("start-system-server")) {

                               startSystemServer();

                           } else if(!argv[1].equals("")) {

                               throw newRuntimeException(argv[0] + USAGE_STRING);

                   }

 

                   Log.i(TAG, "Accepting commandsocket connections");

 

                   if (ZYGOTE_FORK_MODE) {

                       runForkMode();

                   } else {

                       runSelectLoopMode();

                   }

 

                   closeServerSocket();

               } catch (MethodAndArgsCaller caller) {

                   caller.run();

               } catch (RuntimeException ex) {

                   Log.e(TAG, "Zygote died withexception", ex);

                   closeServerSocket();

                   throw ex;

               }

        }

    该函数主要功能如下:

    (1)启动服务端的socket

    (2)调用preload(),预加载java相关类及资源。

    (3)Fork子进程SystemServer,所谓fork就是子进程复制父进程的资源,而且只有在子进程或父进程有写操作时,

            才进行复制,可节省启动时间。

    (4)通过socket监听子进程的请求,然后启动相应服务

            从以上分析可知,zygote主要负责启动java虚拟机,注册jni函数,预加载java相关类及资源,启动systemserver

      子进程,最后监听子进程的请求,启动响服务。自此,我们需要继跟踪systemserver子进程,才能继续追溯启动

      流程。

 

4. SystemServer分析

     分析zygote启动SystemServer的函数startSystemServer()可知,zygote卵化出了systemserver进程,最后调用到 

     SystemServer类的main函数,该函数执行的功能主要如下:

      public staticvoid main(String[] args) {

          …

          System.loadLibrary("android_servers");

          init1(args);

      }

     调用android_server_SystemServer_init1函数,该函数如下:

      static voidandroid_server_SystemServer_init1(JNIEnv* env, jobject clazz)

      {

            system_init();

      }

     又调用system_init,如下:

      extern"C" status_t system_init()

      {

           …

           char propBuf[PROPERTY_VALUE_MAX];

           property_get("system_init.startsurfaceflinger", propBuf,"1");

           if (strcmp(propBuf, "1") == 0) {

               //Start the SurfaceFlinger

               SurfaceFlinger::instantiate();

            }

            …

            jclass clazz =env->FindClass("com/android/server/SystemServer");

            if (clazz == NULL) {

                return UNKNOWN_ERROR;

            }

            jmethodID methodId =env->GetStaticMethodID(clazz, "init2", "()V");

            if (methodId == NULL) {

                return UNKNOWN_ERROR;

            }

            env->CallStaticVoidMethod(clazz,methodId);

 

            LOGI("System server: entering threadpool.\n");

            ProcessState::self()->startThreadPool();

            IPCThreadState::self()->joinThreadPool();

            LOGI("System server: exiting threadpool.\n");

 

            return NO_ERROR;

      }

     反过来调用SystemServerinit2,如下:

      public staticfinal void init2() {

            Slog.i(TAG, "Entered the Androidsystem server!");

            Thread thr = new ServerThread();

            thr.setName("android.server.ServerThread");

            thr.start();

     }

    这里启动了一个ServiceThread线程,最终会执行里面的run函数

     public voidrun() {

           Slog.i(TAG, "Power Manager");

           power = new PowerManagerService();

           ServiceManager.addService(Context.POWER_SERVICE, power);

 

           Slog.i(TAG, "Activity Manager");

           context = ActivityManagerService.main(factoryTest);

 

           Slog.i(TAG, "Telephony Registry");

           ServiceManager.addService("telephony.registry", newTelephonyRegistry(context));

 

           AttributeCache.init(context);

 

           Slog.i(TAG, "Package Manager");

           // Only run "core" apps if we're encrypting the device.

           String cryptState = SystemProperties.get("vold.decrypt");

           boolean onlyCore = false;

           if (ENCRYPTING_STATE.equals(cryptState)) {

                Slog.w(TAG, "Detectedencryption in progress - only parsing core apps");

                onlyCore = true;

           } else if (ENCRYPTED_STATE.equals(cryptState)) {

                Slog.w(TAG, "Deviceencrypted - only parsing core apps");

                onlyCore = true;

           }

 

           pm = PackageManagerService.main(context,

                    factoryTest !=SystemServer.FACTORY_TEST_OFF,

                    onlyCore);

           boolean firstBoot = false;

           try {

                firstBoot = pm.isFirstBoot();

            } catch (RemoteException e) {

           }

 

           ActivityManagerService.setSystemProcess();…

                     …

       }

     该代码很长,但一看就知道,这里启动了java世界的各种服务线程,包括ActivityManagerService

PackageManagerService.等。

     其中PackageManagerService服务线程就是扫描系统的所有app/system/app/data/app

     /data/dalvik-cache/system/framework/*.apk;*.jar/data/secure/data/drm/data/app-private/data/data.

并预加载。

     再看看与ActivityManagerService相关的内容:

      context = ActivityManagerService.main(factoryTest);

      ActivityManagerService.setSystemProcess();

      ActivityManagerService.installSystemProviders();

      ActivityManagerService.self().systemReady

     其中在systemReady函数最后一句,

      mMainStack.resumeTopActivityLocked(null)

     具体代码如下:

      final booleanresumeTopActivityLocked(ActivityRecord prev) {

           // Find the first activity that is not finishing.

           ActivityRecord next = topRunningActivityLocked(null);

 

           // Remember how we'll process this pause/resume situation, and ensure

           // that the state is reset however we wind up proceeding.

           final boolean userLeaving = mUserLeaving;

           mUserLeaving = false;

 

           if (next == null) {

               // There are no more activities! Let's just start up the

               // Launcher...

               if (mMainStack) {

                    returnmService.startHomeActivityLocked();

               }

           }

       }

          分析代码可知,如果任务队列中有activity,则执行第一个activity,如果没有的话,则启动home程序。由于系统

   一开始并没有activity,则启动home程序。


 
5. 第一个Activity

         通过上述分析,系统终于启动完毕了,第一个activity产生。值得注意的是,ActivityManagerService

    startHomeActivityLocked,实际上系统发出了一个category字段包含CATEGORY_HOMEintent,如下代码:

    if (mFactoryTest!= SystemServer.FACTORY_TEST_LOW_LEVEL) {

           intent.addCategory(Intent.CATEGORY_HOME);

    }

          无论是哪个应用程序,只要声明自己能够响应intent,那么久可以认为是home程序。当系统中有多个程序能够

   响应该intent是,系统会弹出一个框,请求用户选择哪个应用程序。当用户选择完,之后每次按home键,系统都会

   执行选择的home activity

 

二、开机启动界面

1. 开机logo

          在init流程时,有一个console_init,里面会加载android系统启动LOGO,如果该LOGO不在,将默认显示

    android字样。另外,该LOGO是直接写FRAMEBUFFER的,所以不需要依赖于surface,这个同开机动画不同。

 

2. 开机动画

          系统启动的开机动画,源码里默认是没有的,所以总会跳到android字体闪动的画面。这个闪动的android字体

     实际上是两张图,一张镂空的android图,一张发光效果,动画效果就是下面那张发光的效果图不断左右移动,

     这两张图存放在:

      android4.0.1\frameworks\base\core\res\assets\images

     那如何添加自己的开机动画呢?方法如下:

     制作一个bootanimation.zip包,然后把它放到/system/media/目录下,重新打包固件。

     至于它是如何启动的,还得返回来看看system_init()这个函数,有

      SurfaceFlinger::instantiate();

     这个函数实际上是把surfaceflinger实例化,最终启动surfaceflinger服务,调用surfaceflingerreadyToRun(),

     如下:

      status_t SurfaceFlinger::readyToRun()

     {

          ……

          // start boot animation

          property_set("ctl.start","bootanim");

          return NO_ERROR;

       }

      这里,init.rc里面记录的bootanim进程被创建,开机动画由这个进程放出来。

      继续分析,我们回到init.c

    int main()

    {

       struct pollfd ufds[4];

       ……

       if (!property_set_fd_init && get_property_set_fd()> 0) { //为property创建一个socket
           ufds[fd_count].fd = get_property_set_fd();
           ufds[fd_count].events = POLLIN;
           ufds[fd_count].revents = 0;
            fd_count++;
           property_set_fd_init = 1;
        }

 

    nr =poll(ufds, fd_count, timeout); //等待socket事件到来

    for(i = 0; i < fd_count; i++) {
            if(ufds[i].revents == POLLIN) {
               if (ufds[i].fd == get_property_set_fd())  //处理property设置事件

                   handle_property_set_fd();
               else if (ufds[i].fd == get_keychord_fd())
                   handle_keychord();
               else if (ufds[i].fd == get_signal_fd())
                   handle_signal();
            }
        }

     }

         ……

     }

    看看handle_property_set_fd

   voidhandle_property_set_fd()
   {

       r = recv(s, &msg, sizeof(msg), 0);

       switch(msg.cmd) {
         casePROP_MSG_SETPROP:
           msg.name[PROP_NAME_MAX-1]= 0;
           msg.value[PROP_VALUE_MAX-1]= 0;

           if(memcmp(msg.name,"ctl.",4) == 0) {
              if (check_control_perms(msg.value, cr.uid,cr.gid)) {
                  handle_control_message((char*)msg.name + 4, (char*) msg.value);
              }else{
                  ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n",
                       msg.name + 4, msg.value, cr.uid, cr.pid);
              }
           }

       }

    }

    再调用handle_control_message,如下

    voidmsg_start(const char *name)

    {

        if(svc) {
            service_start(svc, args);
        }

    }

 

    这样,开机动画的bootanim就启动了。