Android系统启动过程介绍

DVM与ART的区别?

5.0后Android runtime由DVM改成ART,区别是?

DVM:

应用运行时,即时编译器将字节码编译成机器码,使得应用运行效率低

ART:

应用安装时,提前进行一次预编译,将字节码编译成机器码存储在本地,这样应用运行时就不用再编译一次了,运行效率大大提高。

Android 系统启动过程

Android 系统启动过程涉及到很多系统进程的启动以及各类服务的创建,首先来看一下总的过程概览:

在这里插入图片描述

步骤一 启动init进程

Android从按下电源到启动会经过很多个步骤,现在一个个的来看,首先启动的是init进程,它是用户空间的第一个进行,进程号为1;init进程主要做三件事:

  1. 创建和挂载启动所需的文件目录
  2. 初始化和启动属性服务
  3. 解析init.rc配置文件且启动Zygote进程

步骤二 启动Zygote进程

zygote是啥?

init进程启动后,会创建一个zygote进程,然后由这个zygote进程去创建DVM、ART虚拟机、应用程序进程以及运行系统关键服务的SystemServer,zygote创建时就会创建DVM、ART,再通过fork(叉子)去创建应用程序进程以及SystemServer.

fork进程是什么意思?

可以理解为克隆,父进程通过fork创建出子进程,子进程是父进程的副本,可以获得父进程的数据空间、堆、栈的副本,不与父进程共享存储空间。

init进程经过Runtime,通过JNI调用zygote的ZygoteInit类的main()方法,zygote得以从Native层进入Java框架层,可以在studio中看到ZygoteInit类以及对应的main()方法,这个main()方法主要做几件事:

//1.创建一个Server端的socket,名为zygote,内部就是启动一个LocalServerSocket。
zygoteServer.registerServerSocket(socketName);

//2.预加载类和资源
preload(bootTimingsTraceLog);

//3.启动SystemServer进程,系统服务也因此启动起来
if (startSystemServer) {
    startSystemServer(abiList, socketName, zygoteServer);
 }
//4.等待AMS请求zygote创建新的应用程序进程。
zygoteServer.runSelectLoop(abiList);

具体看下如何启动SystemServer?

private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller, RuntimeException {

   //1.创建args数组,用于补充Systemserver的启动参数,例如uid、pid、群组,进程名,可见用户id和用户组id均是1000,且拥有用户组1000~1010,1021、1032、3001~3010的权限
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            //2.Zygote通过fork创建一个子进程,即创建一个Zygote进程的子进程SystemServer
            pid = Zygote.forkSystemServer(param);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        //3.表明当前代码运行在子进程中
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
			  //因为子进程是复制出来的,所以也有一个socket,但是对于SystemServer是没用的,所以close()
            zygoteServer.closeServerSocket();
            //4.处理SystemServer进程
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

再来看下如何通过runSelectLoop来等待AMS创建应用程序进程?

死循环等待AMS的请求,有了请求,就去创建新的应用程序进程,并添加到链接列表中。

    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

		 //1.这个mServerSocket就是第一步中创建的服务端Socket
        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);
		 //无限循环等待AMS的请求zygote进程创建新的应用进程
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            
            //2.将文件描述符数组fds转移到pollFds数组
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            //3.遍历pollFds,如果i == 0,说明服务端socket和客户端链接上了,即zygote进程和AMS建立了链接
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
        
                if (i == 0) {
                //4.添加该connection到peers列表中
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                   //5.如果i != 0,说明AMS向zygote发来一个新的创建应用程序进程请求,则调用runOnce()创建一个,创建成功,从列表中删除该链接。
                    boolean done = peers.get(i).runOnce(this);
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

SystemServer的处理过程

上面创建SystemServer的过程中,有一行代码:

handleSystemServerProcess(parsedArgs); //干什么的?这行代码会调用到ZygoteInit的zygoteInit()方法,去看看这个方法做了什么事情?

zygoteInit()

public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit(); //这里调用了native的方法,用来启动Binder线程池,这样一来,SystemServer进程就可以使用Binder与其他进程进行通信了。前面所有流程中,Binder还没创建。
        //进入SystemServer的main方法
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
1.如何启动Binder线程池

ZygoteInit.nativeZygoteInit()的代码位于frameworks/base/core/jni/AndroidRuntime.cpp中,内部调用的是frameworks/base/cmds/app_process/app_main.cpp的onZygoteInit()方法,具体如下:

 virtual void onZygoteInit(){    
    sp<ProcessState> proc = ProcessState::self();
	 ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool();  //通过调用ProcessState的startThreadPool()来创建Binder线程池
  }

ProcessState创建Binder线程池的具体代码:

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
       ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = new PoolThread(isMain); //创建线程并运行
        t->run(name.string());
    }
}

2.SystemServer进程如何启动系统服务?

直接来看看SystemServer的main()方法:

 public static void main(String[] args) {
        new SystemServer().run(); //这里只是调用了它的run()方法,那它的run()方法又做了啥?
    }

run():

private void run() {
        try {
           ...
            //创建消息Looper
            Looper.prepareMainLooper();

            // 1. 加载了动态库libandroid_servers.so
            System.loadLibrary("android_servers");

            performPendingShutdown();

            //创建系统的Context
            createSystemContext();

            // 2.创建系统ServiceManager,它是对系统服务进行创建、启动以及生命周期管理
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();    
         }

       
        try {
            traceBeginAndSlog("StartServices");
            
            //3. 启动引导服务,这里很重要,通过mSystemServiceManager去启动AMS、PMS
            startBootstrapServices();
            
            //4. 启动核心服务,例如BatteryService、WebViewUpdateService
            startCoreServices();
            
            //5.启动其他服务,例如CameraService、WMS,这些服务的父类均为SystemService.都是通过mSystemServiceManager.startService(“ServiceName”.class)来创建
            startOtherServices();
            
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

SystemServiceManager如何创建各类Service,去看看它的startService():

public void startService(@NonNull final SystemService service) {
        // 所有创建的Service都要添加到一个ArrayList中方便管理
        mServices.add(service);
        // Start it.
        long time = System.currentTimeMillis();
        try {
           //启动Service
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(System.currentTimeMillis() - time, service, "onStart");
    }

也可以通过具体Service的main()方法来创建,例如PackageManagerService.main()

public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        // 初始化设置检测
        PackageManagerServiceCompilerMapping.checkProperties();
		 //1. 直接new一个示例
        PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
        m.enableSystemUserPackages();
        //2.添加到ServiceManager中
        ServiceManager.addService("package", m);
        return m;
    }

ServiceManager用来管理各种Service,当client要使用Service时,先去 ServiceManager查询该Service的相关信息,然后根据该Service的相关信息以及所在进程和client建立通信通道,这样client就可以使用service了。

步骤三 启动Launcher

系统启动的最后一步,启动一个应用程序显示系统中所有已安装的应用程序,这个应用程序就是Launcher,它在启动时会去向PackageManagerService请求获取所有安装的应用程序,并将所有应用程序的快捷图标显示在桌面上,这样用户就可以通过点击图标来启动指定的应用程序。

可以认为Launcher就是android的桌面,它主要做2个事情:

  1. 显示和管理应用程序的快捷图标
  2. 用于启动应用程序

Launcher启动过程介绍:

  1. 启动入口 : AMS的systemReady方法,代码如下,在SystemServer的startOtherServices()中:
private void startOtherServices() {
 ...
 mActivityManagerService.systemReady(() -> {
            Slog.i(TAG, "Making services ready");
            traceBeginAndSlog("StartActivityManagerReadyPhase");
            mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
            traceEnd();
            
...
}      
...      
  1. 看一下AMS的syatemReady():
public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
  ...
  synchronized(this) {
   mStackSupervisor.resumeFocusedStackTopActivityLocked(); //这里又进入了StackSupervisor的resumeFocusedStackTopActivityLocked()
   mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
   ...
 }  
   
  1. 那么在StackSupervisor的resumeFocusedStackTopActivityLocked()又做了什么?
 boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); //这中间经过一系列的跳转,会进入到ActivityStackSupervisor的resumeHomeStackTask()中
        }
        ...
        return false;
    }
  1. ActivityStackSupervisor的resumeHomeStackTask()又做了什么?
boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
	...
   if (prev != null) {
            prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
        }

        mHomeStack.moveHomeStackTaskToTop();
        ActivityRecord r = getHomeActivity();
        final String myReason = reason + " resumeHomeStackTask";

        // Only resume home activity if isn't finishing.
        if (r != null && !r.finishing) {
            moveFocusableActivityStackToFrontLocked(r, myReason);
            return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
        }
        return mService.startHomeActivityLocked(mCurrentUser, myReason);  //主要工作就是调用AMS去启动HomeActivity
    }
    
  1. AMS的startHomeActivityLocked()方法:
boolean startHomeActivityLocked(int userId, String reason) {
		 //1. 	mFactoryTest代表系统的运行模式,分为非工厂模式、低级工厂模式、高级工厂模式,mTopAction表示第一个启动的activity的action,默认是:Intent.ACTION_MAIN.
		 //如果mFactoryTest为低级工厂模式,且mTopAction == null不符合下面要求,则返回false
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL&& mTopAction == null) {
            return false;
        }
        //2. 这里返回了一个category为Intent.CATEGORY_HONE的intent
        Intent intent = getHomeIntent();
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,aInfo.applicationInfo.uid, true);
            
            //3. 判断Action为 Intent.ACTION_MAIN且Category为 Intent.CATEGORY_HONE的应用程序是否已经启动,没有则调用4的方法进行启动,这个程序就是Launcher,可以从它的			 // AndroidManifest.xml文件里面查看它的定义的intent-fliter。   
            if (app == null || app.instr == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                final String myReason = reason + ":" + userId + ":" + resolvedUserId;
                //4.调用ActivityStarter的startHomeActivityLocked来启动Launcher
                mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
        }

        return true;
    }

  1. ActivityStarter的startHomeActivityLocked来启动Launcher
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
		 // 1. 将Launcher放入HomeStack中,	HomeStack是ActivityStackSupervisor中用于存储Launcher的变量。
        mSupervisor.moveHomeStackTaskToTop(reason);
        // 2.调用startActivityLock()来启动Launcher,和正常启动Activity的过程一样。
        mLastHomeActivityStartResult = startActivityLocked(...params);
        if (mSupervisor.inResumeTopActivity) {
            // If we are in resume section already, home activity will be initialized, but not
            // resumed (to avoid recursive resume) and will stay that way until something pokes it
            // again. We need to schedule another resume.
            mSupervisor.scheduleResumeTopActivities();
        }
    }

至此,就完成了Launcher的启动。Android整个系统的启动过程也大致完毕。

猜你喜欢

转载自blog.csdn.net/qq_26984087/article/details/89019636