Android 系统启动过程简略分析

摘要:Android系统启动的过程可概括为init进程启动、Native服务启动、SystemServer,Android服务启动和Home启动4个步骤。各个步骤紧密联系一环紧扣一环,是一个统一的整体。

关键字:init进程;Zygote进程;SystemServer

1 Android OS架构

Android 系统采用了分层架构,分为4个层次,从高层到底层分别是应用程序层、应用层许框架层、系统运行库层、和Linux核心层。观察Android系统架构图可以发现,其提供的基本应用程序(Home,Camera,Dialer,Browser等)运行在应用程序框架之上。对开发者而言,开发者可以借助Android SDK,调用应用程序框架API开发出应用也运行在应用程序框架层之上。


 
                                               
 

 

                                             Android系统架构图

    Android系统的各个层次都有不同的功能,在这里不做过多的概述只初步的了解一下。

2 init进程及其启动

init进程是一个用户级进程,init有许多重要任务,比如像启动getty(用于用户登录)、实现运行级别、以及处理孤立进程init始终是第一个进程。

启动时,首先通过bootloader(系统加载器),加载Linux内核。在Linux加载启动内核时,与普通的Linux启动过程相同,先初始化内核,然后调用init进程。

                                                               
 

 

                                        init进程启动过程

由init进程启动图可以看出,init进程是在顺序执行完start_kernel()函数、init_post()函数、run_init_process()函数后,最后执行的。实现init进程启动的代码如下:

Static int noinline init_post(void)

{

    if(execute_command){

       run_init_process(execute_command);

    }

   run_init_process(“/sbin/init”);

   run_init_process(“/etc/init”);

   run_init_process(“/bin/init”);

}

Android init进程对各种设备进行初始化,运行Android Framework所需要的各种Daemon、ServiceManager、Zygote等。其中ServiceManager是一个管理Android系统服务的重要进程。系统服务是组成Android Framework的重要组件,提供相机、音频、视频、处理到各种应用程序制作所需要的重要API。

init进程不仅进行子进程的终止处理,当应用程序访问设备驱动时,还会生成设备节点文件,同时提供属性服务,保存系统运行所需的环境变量。此外,它还会分析init.rc启动脚本文件,并根据相关文件中包含的内容,执行相应的功能。

Android启动时,init.rc脚本文件用来设置系统环境,记录待执行的进程;二是action list与service list相关的内容,它们是由init进程根据init.rc生成的。Init.rc文件结构如下

                                                                                                                           
 

 

init.rc文件结构

2.1 动作列表(Action List)

    在动作列表的“on init”段落中,主要设置环境变量,生成系统运行所需的文件或目录,修改相应的权限,并挂载与系统运行相关的目录。

                                       
 

 

                                                  on init段落 

    在“on init”根文件系统挂载部分,主要挂载/system与/data两个目录。两个目录挂载完毕后,Android根文件系统就准备好了。

2.2 服务列表(Service List)

在init.rc脚本文件中,“service”段落用来记录init进程启动的进程。由init进程启动的子进程或是一次性程序,或是运行在后台的与应用程序、系统服务管理相关的ServiceManager进程等。

                                                       
 
                                         
 


 

最后init进程并不退出,而是担当起属性服务(property service)的功能。

3 Zygote进程

从字面上看Zygote是“受精卵、结合子、结合体”的意思。在Android系统中运行新的应用,如同卵子受精分裂一样需要跟Zygote进程(拥有应用程序运行时所需的各种元素与条件)结合后才能执行。Zygote是Android系统应用中的一个相当重要的进程,它的主要功能

就是执行Android应用程序。

Zygote进程运行时,会初始化Dalvik虚拟机,并启动它。Android的应用程序时由java编写的,他们不能直接以本地进程的形态运行在Linux上,只能运行在Dalvik虚拟机中。此时我们就可以和Android的架构对应起来了,此时系统已经运行到系统运行库层。Android的服务与应用程序都由Zygote进程启动运行。

由app_process运行ZygoteInit class

Zygote由java编写而成,不能直接由init进程启动运行。若想运行Zygote类,必须先生成Dalvik虚拟机,再在Dalvik虚拟机上装载运行ZygoteInit类,执行这一任务的就是app_process进程。app_process进程执行时,首先常见AppRuntime对象。部分源代码如下

int main(){

     ...

    AppRuntime runtime;

    ..

    //Everything up to ‘--’ or first non ‘-’ arg goes to the *vm

    int i = runtime.addVmArguments(argc,argv);

    //Next arg is parent directory

    if(i

       runtime.mParentDir = argv[i++];

    }

}

AppRuntime类继承自AndroidRuntime类,AndroidRuntime类运行于初始化并运行Dalvik虚拟机之前,通过AppRuntime对象,分析环境变量以及运行参数,并以此生成虚拟机选项。分析完要传递给虚拟机的参数,并保存到AppRuntime类的对象中,而后加载对象,调用对象的main()方法。

int main(int argc ,const char* const argv[]){

   ...

   if(i 

     arg =  argv[i++];

   if(0 == strcmp(“--zygote”,arg)){

      bool startSyatemServer = (i < argc)?

            strcmp(argv[i],”--start-system-server”) == 0:false;

      setArgv0(argv0,”zygote”);

      set_process_name(“zygote”);

      //生成并初始化虚拟机

      runtime.start(“com.android.internal.os.ZygoteInit”

             ,startSystemSever);

   }else {...}

   }

   ...

}

Dalvik虚拟机由runtime启动并初始化(见上面注释),而后将ZygoteInit类加载至虚拟机中,执行其中的main方法。

ZygoteInit类的主要有四大功能,分别是绑定/dev/socket/zygote套接字、加载应用程序Framework中的类与平台资源、运行SystemServer和运行新的Android应用程序。在这里我们只初步解释其中的部分功能。ZygoteInit::main()方法的主要功能如下图:

                                                         

                                                     ZygoteInit功能图

下面我们先看一下ZygoteInit类的部分源代码。

public static void main(String argv[]){

     try{

        //绑定套接字,接受新的Android应用程序请求

        registerZygoteSocket();

        ...

        //加载Android Application Framework使用的类资源

        preloadClasses();

        preloasResources();

        ...

        //运行SystemSever

        if(argv[1].equals(“true”)){

           startSystemServer();

        }

        ...

        if(ZYGOTE_FORK_MODE){

            runForkMode();

        }else {

            //处理新Android应用程序运行请求

            runSelectLoopMode();

        }

        closeSeverSocket();

    }catch(MethodANdArgsCaller caller){

        caller.run();

    }catch(RuntimeException ex){

        log.e(TAG,”Zygote died with exception”,ex);

        closeServerSocket();

        throw ex;

    }

}

ZygoteInit类会调用preloadClasses()与preloadResources()两个方法,这两个方法分别用于将应用程序Framework中的类,以及图标、图像、字符串等资源加载到内存之中,并对装载的类与资源生成链接信息。新生成的Android应用程序在使用这些已经装载的类或资源时,直接使即可。至此,Dalvik虚拟机已经启动并完成初始化,还绑定了套接字,以便接收应用程序的创建请求。并且,包含应用程序Framework中的类与资源也被加载到内存之中。由此ZygoteInit类做好了接收请求创建应用程序并运行的准备。但ZygoteInit在处理应用程序创建请求之前,还有一项工作就是运行SystemServer。

Zygote进程启动Dalvik虚拟机后,会在生成一个Dalvik虚拟机实例,以便运行名称为SystemServer的java服务,SystemServer用于运行Audio Flinger与Surface Flinger本地服务。在运行完所需要的本地服务之后,SystemServer开始运行Android Framework的服务,如ActivityManager(管理Android应用程序的Activity)、PackageManager(设置或安装应用程序)等。

4 Home启动和其他应用程序的启动

4.1 应用程序的启动 

   在SystemSever运行后,程序会进入一个循环,处理来自所绑定的套接字请求。若ZYGOTE_FORK_MODE为false,程序就会调用runSelectLoopMode()方法,直到zygote进程终止,该方法才返回。

接下来看一下runSelectLoopMode的部分源代码。

private static void runSelectLoopMode() throws MethodAndArgsCaller{

      ......

      fds.add(sSeverSocket.getFileDescriptor());

       while(true){

           ......

           index = selectReadable(fdArray);

           ......

           if(index <0){

               throw new RuntimeException("Error in select()");

           }

           else if(index ==0){

              ZygoteConnection newPeer = acceptCommandPeer();

              peers.add(newPeer);

              fds.add(newPeer.getFileDescriptor());

           }

           else {

               boolean done;

               done = peers.get(index).runOnce();

               if(done){

                   peers.remove(index);

                   fds.remove(index);

               }

           }

       }

}

donr = peers.get(index).runOnce()这行代码用于处理新连接的输入输出套接字,并生成新的Android应用程序,具体过程如下。

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller{

     ...

     try{

        args = readArgumentList();

        ...

     }

     ...

     int pid;

     try{

        parseArgs =new Arguments(args);

        applyUidSecurityPolicy(pareseArgs,peer);

        applyDebuggerSecurityPolicy(parseArgs);

        applyRlimitSecurityPolicy(parsedArgs,peer);

        applyCapailitiesSecurityPolicy(parseArgs,peer);

       int[][] rlimits = null;

       if(parsedArgs.rlimits != null){

          rlimits = paresedArgs.rlimits.toArry(intArray2d);

       }

       pid = Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlagd,rlimits);

     }

     ......

}

runOnce()函数分析请求信息中的字符串数组,为运行进程设置好各个选项,具体包括设置应用程序的gid、uid,调试标记处理,设置rlimit,以及检查运行权限等。之后就可以创建新进程了,Zygote.forkAndSpecialize()方法接受上面分析好的参数,调用Zygote类的本地方法forkAndSpecialize()。然后调用本地函数fork(),创建新进程,并根据新创建的进程传递的选项,设置uid、gid、rlimit等。此时,新运行的应用程序就已经启动完成了。新运行的应用程序由ZygoteInit类动态加载,共用装载到父进程生成虚拟机代码。并且,共应用程序FrameWork中的类及资源的链接信息,这大大加快了应用程序创建与启动的速度。

4.2 Home的启动

Activity的启动必然和ActivityManagerService的启动有关,下面是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...

                  ActivityManagerService.systemReady( );

                  appWidgetF.systemReady(safeMode);

                  wallpaperF.systemReady();

           }

    });

 

    //

    //BOOTPROF

    addBootEvent(new String("Android:SysServerInit_END"));

    Looper.loop();

}

从上面可以看出系统在启动完所有的Android服务后,做了这样一些动作,使用xxx.systemReady()通知各个服务,系统已经就绪。其中也包括ActivityManagerService.system-

Ready( )的回调。Home就是在ActivityManagerService.systemReady( )通知的过程建立的。

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

    }

  }

  ……

}

从上面分析得出HomeActivity在执行mService.startHomeAct-

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

                                                                                           
 

 

5 结语

   Android系统层次结构分别为应用程序层、应用层许框架层、系统运行库层、和Linux核心层四应用程序层、应用层许框架层、系统运行库层、和Linux核心层层。各层都有自己的功能,Linux核心层面向底层硬件,系统运行层支撑整个系统,应用层支撑应用程序层,应用程序层面向用户为用户提供良好的交互界面。本文即是在Linux核心层的基础之上出发,绕过硬件层简要的阐述了Android系统的启动过程。

      关于这篇文章有很多地方加入了自己的理解,有很多不足之处望理解

你可能感兴趣的:(Study,android,linux内核)