Android系统启动流程

一、启动电源以及系统启动

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

二、引导程序BootLoader

这是Android操作系统开始运行前的一个小程序,主要作用是初始化基本的硬件设备,建立内存空间映射, 为装载linux内核准备好运行环境,当linux内核加载完毕之后,bootloder就会从内存中清除。

三、Linux内核启动

当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设置后,它首先在系统文件中寻找init.rc文件,并启动init进程。

四、init进程启动

init进程是Linux创建的第一个进程,主要做了一下三件事:

(1)创建和挂载启动所需的文件目录。

(2)初始化和启动属性服务。

(3)解析init.rc配置文件并启动Zygote进程。

五、Zygote进程启动

Zygote进程是所有进程的父进程,Zygote进程初始化的时候会创建Dalivik虚拟机预装载系统的资源文件和java类,通过fock(复制进程)的形式来创建应用程序进程和运行系统的关键服务的SystemServer进程,所有从Zygote进程fock出的用户进程将继承和共享这些资源(在内部获取一个DVM的实例副本),不用浪费时间重新加载。在这之后,Zygote进程也将变为守护进程,负责响应启动APK应用的启动请求

首先由app_process可执行文件创建AppRuntime(具体代码见下文)并调用其start方法,启动Zygote进程,再创建Java虚拟机并为Java虚拟机注册JNI方法,通过JNI调用了ZygoteInit的main函数进入Zygote的Java框架层,这就从C++代码跳到了java代码ZygoteInit类通过调用zygoteServer的registerServerSocket方法来创建一个Server端的Socket,再通过runSelectLoop方法来等待AMS请求创建新的应用程序进程。由上图可以看出,ZygoteInit类还做了两件事:预加载类和资源、启动SystemServer进程。Zygote进程将SystemServer进程启动之后,就会转为守护进程,在这个服务器端的Socket上等待AMS请求。

下面具体来看看启动SystemServer进程。

六、SystemServer进程启动

SystemServer进程是Zygote进程fork出的第一个进程,也是整个Android系统的核心进程,在SystemServer主要运行的是Binder服务,通过nativeZygoteInit函数启动Binder线程池,SystemServer进程可以使用Binder与其他进程进行通信。再创建SystemServiceManager,用于对系统的服务进行创建、启动和生命周期管理。SystemServer首要启动本地服务 SensorService接着启动 ActivityManagerService,WindowsManagerService,PackgeManagerService等在内的所有java服务

七、Launcher启动

系统启动的最后一步是启动一个应用程序用来显示系统中已经安装的应用程序,这个应用程序就叫作Launcher。Launcher在启动过程中会请求PackageManagerService返回系统中已安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户就可以通过点击这些快捷图标来启动相应的应用程序。

启动Launcher的入口为AMS的systemReady方法(具体调用代码见后文),代码调用顺序见Launcher启动过程的时序图,最终resumeHomeStackTask方法中调用了AMS的startHomeActivityLocked方法。将Launcher放入HomeStack中,接着调用startActivityLocked方法来启动Launcher,剩余的过程和Activity的启动过程类似。下篇讲Activity的启动过程。最终进入Launcher的onCreate方法中,到这里Launcher就完成了启动。

具体代码执行的流程如下:

  1. Init进程首先加载一个init.rc配置文件(Android启动脚本),代码如下:

    int main(int argc, char **argv)
    {   
    // 创建文件夹 挂载
        mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
        mkdir("/dev/pts", 0755);
       
        // 打开日志
        log_init();
        
        INFO("reading config file\n");
        // 加载init.rc配置文件
        init_parse_config_file("/init.rc");
    
    } 
    
  2. init.rc配置文件会进行很多的配置,创建很多的文件夹及文件,然后初始化一些Android驱动器,之后该配置文件最重要的一个任务就是启动一个Zygote(孵化器)进程,此进程是Android系统的一个父进程,用来启动Android的其他服务进程,代码如下:

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd

  3. Zygote会执行一个app_process可执行文件,在这个文件中首先添加了Android运行时环境,在Android运行时中调用了ZygoteInit类,这就从C++代码跳到了java代码

    int main(int argc, const char* const argv[])
    {
        ...
        // Android运行时环境
        AppRuntime runtime;
        ...
        // Next arg is startup classname or "--zygote"
        if (i < argc) {
            arg = argv[i++];
            if (0 == strcmp("--zygote", arg)) {
                bool startSystemServer = (i < argc) ? 
                        strcmp(argv[i], "--start-system-server") == 0 : false;
                setArgv0(argv0, "zygote");
                set_process_name("zygote");
                // 启动java代码
                runtime.start("com.android.internal.os.ZygoteInit",
             ...
    
    }
    
  4. 进入AppRuntime.start方法。因为AppRuntime继承AndroidRuntime。所以会调用到AndroidRuntime.start方法:注册一系列本地函数到虚拟机,通过反射机制找到ZygoteInit.main方法并执行。

    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    { //app_main.cpp  runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
     //className:com.android.internal.os.ZygoteInit       zygote:true
         ...
         //注册JNI本地函数
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
         ...
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
            /* keep going */
        } else {
        //ZygoteInit 通过反射找到zygoteInit.main的方法ID。
            jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
            if (startMeth == NULL) {
                ALOGE("JavaVM unable to find main() in '%s'\n", className);
                /* keep going */
            } else {
            //执行zygoteinit.main方法,zygoteinit类为java类
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
          ...
    }
    
  5. ZygoteInit.main.java代码中首先设置了Java虚拟机的堆内存空间,然后启动一个类加载器加载Android启动依赖的类比如Activity等四大组件,dialog等UI的类,然后分出一个子进程启动SystemServer系统服务

      // ZygoteInit.mian 
    public static void main(String argv[]) {
            try {
                VMRuntime.getRuntime().setMinimumHeapSize(5 * 1024 * 1024);
                 //1.注册socket
                // 2.加载Android依赖的类
                preloadClasses();
                //cacheRegisterMaps();
                preloadResources();
                ...
                 if (argv[1].equals("true")) {
                // 3.启动系统服务进程,最终调用SystemServer.main方法
                startSystemServer();
            } else if (!argv[1].equals("false")) {
           ...
                // 4.进入循环
    }
    private static boolean startSystemServer()
         ...
            args = new String[] {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006",
                "--capabilities=130104352,130104352",
                "--rlimit=8,",
                "--runtime-init",
                "--nice-name=system_server",
                "com.android.server.SystemServer",
          ... 
       /* Request to fork the system server process */
        // 母进程开始分叉服务 启动SystemServer 
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids, debugFlags, rlimits,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
             ...
    }
    
  6. 在SystemServer.main里初始化SystemServer对象,再调用对象的run()方法

    public final class SystemServer {
        ...
        public static void main(String[] args) {
            //先初始化SystemServer对象,再调用对象的run()方法,
            new SystemServer().run();
        }
    }
    
  7. SystemServer.run()用于启动各种系统服务

    private void run() {
        //当系统时间比1970年更早,就设置当前系统时间为1970年
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }
    //变更虚拟机的库文件,对于Android 6.0默认采用的是libart.so
    SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
     
    if (SamplingProfilerIntegration.isEnabled()) {
        ...
    }
     
    //清除vm内存增长上限,由于启动过程需要较多的虚拟机内存空间
    VMRuntime.getRuntime().clearGrowthLimit();
     
    //设置内存的可能有效使用率为0.8
    VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
    // 针对部分设备依赖于运行时就产生指纹信息,因此需要在开机完成前已经定义
    Build.ensureFingerprintProperty();
     
    //访问环境变量前,需要明确地指定用户
    Environment.setUserRequired(true);
     
    //确保当前系统进程的binder调用,总是运行在前台优先级(foreground priority)
    BinderInternal.disableBackgroundScheduling(true);
    android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
    android.os.Process.setCanSelfBackground(false);
     
    // 主线程looper就在当前线程运行
    Looper.prepareMainLooper();
     
    //加载android_servers.so库,该库包含的源码在frameworks/base/services/目录下
    System.loadLibrary("android_servers");
     
    //检测上次关机过程是否失败,该方法可能不会返回[见小节1.2.1]
    performPendingShutdown();
     
    //初始化系统上下文 
    createSystemContext();
     
    //创建系统服务管理
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    //将mSystemServiceManager添加到本地服务的成员sLocalServiceObjects
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    //启动各种系统服务
    try {
        startBootstrapServices(); // 启动引导服务
        startCoreServices();      // 启动核心服务
        startOtherServices();     // 启动其他服务
    } catch (Throwable ex) {
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    }
     
    //用于debug版本,将log事件不断循环地输出到dropbox(用于分析)
    if (StrictMode.conditionallyEnableDebugLogging()) {
        Slog.i(TAG, "Enabled StrictMode for system server main thread.");
    }
    //一直循环执行
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    
  8. startBootstrapServices方法里主要去启动AMS(ActivityManagerService)

    private void startBootstrapServices() {
        ...
        //启动AMS服务
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
         //设置AMS的系统服务管理器
         mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
         //设置AMS的APP安装器
         mActivityManagerService.setInstaller(installer);
         //初始化AMS相关的PMS
         mActivityManagerService.initPowerManagement();
         ...
     
         //设置SystemServer
         mActivityManagerService.setSystemProcess();
    
  9. startOtherServices方法会调用ActivityManagerService.systemReady方法

       private void startOtherServices() {
        ...
        SystemConfig.getInstance();
        mContentResolver = context.getContentResolver(); // resolver
        ...
        mSystemServiceManager.startService(MOUNT_SERVICE_CLASS); // mount
        mPackageManagerService.performBootDexOpt();  // dexopt操作
        ActivityManagerNative.getDefault().showBootMessage(...); //显示启动界面
        ...
        // 准备好window, power, package, display服务
        wm.systemReady();
        mPowerManagerService.systemReady(...);
        mPackageManagerService.systemReady();
        mDisplayManagerService.systemReady(...);
        
        //重头戏
        mActivityManagerService.systemReady(new Runnable() {
            public void run() {
              ...
            }
        });
    }
    
  10. 在ActivityManagerService的sysytemReady方法中,最关键的是startHomeActivityLocked和resumeTopActivityLocked两个方法,这两者都可以启动lucher应用的锁屏界面

    public void systemReady(final Runnable goingCallback) {
            synchronized(this) {
                    if (mSystemReady) {
            // If we're done calling all the receivers, run the next "boot phase" passed in
            // by the SystemServer
                if (goingCallback != null) {
                     goingCallback.run();
                    }
                return;
                 }    
                    // Make sure we have the current profile info, since it is needed for
            // security checks.
            updateCurrentProfileIdsLocked();
     
            .................................... 此处省略大量代码
            // Start up initial activity.
            mBooting = true;
            //打开
            startHomeActivityLocked(mCurrentUserId, "systemReady");
     
            try {
                if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
                    Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
                            + " data partition or your device will be unstable.");
                    mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
                }
            } catch (RemoteException e) {
            }
     
            if (!Build.isFingerprintConsistent()) {
                Slog.e(TAG, "Build fingerprint is not consistent, warning user");
                mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
            }
     
            long ident = Binder.clearCallingIdentity();
            try {
                Intent intent = new Intent(Intent.ACTION_USER_STARTED);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_FOREGROUND);
                intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
                broadcastIntentLocked(null, null, intent,
                        null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                        false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
                intent = new Intent(Intent.ACTION_USER_STARTING);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
                broadcastIntentLocked(null, null, intent,
                        null, new IIntentReceiver.Stub() {
                            @Override
                            public void performReceive(Intent intent, int resultCode, String data,
                                    Bundle extras, boolean ordered, boolean sticky, int sendingUser)
                                    throws RemoteException {
                            }
                        }, 0, null, null,
                        INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
                        true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
            } catch (Throwable t) {
                Slog.wtf(TAG, "Failed sending first user broadcasts", t);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
          //打开第一个activity
            mStackSupervisor.resumeTopActivitiesLocked();
            sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
        }
    }
    
  11. startHomeActivityLocked方法启动home界面

    boolean startHomeActivityLocked(int userId, String reason) {
            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                    && mTopAction == null) {
                // We are running in factory test mode, but unable to find
                // the factory test app, so just sit around displaying the
                // error message and don't try to start anything.
                return false;
            }
           Intent intent = getHomeIntent();
            ActivityInfo aInfo =
                resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
            if (aInfo != null) {
                intent.setComponent(new ComponentName(
                        aInfo.applicationInfo.packageName, aInfo.name));
                // Don't do this if the home app is currently being
                // instrumented.
                aInfo = new ActivityInfo(aInfo);
                aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
                ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                        aInfo.applicationInfo.uid, true);
                if (app == null || app.instrumentationClass == null) {
                    intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                    mStackSupervisor.startHomeActivity(intent, aInfo, reason);
                }
            }
                    return true;
    }
    
  12. 通过ActivityStack的resumeTopActivityLocked方法调用startHomeActivityLocked来启动home界面

    final boolean resumeTopActivityLocked(ActivityRecord prev) {
        // Find the first activity that is not finishing.
        // 没有已经打开的Activity, next为 null
        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) {
                // 启动lucher应用的锁屏界面
                return mService.startHomeActivityLocked();
            }
            }
            ...
    }
    
  13. startHomeActivityLocked有一个很关键的方法:getHomeIntent(),它就是打开launcher应用的Intent。

    Intent getHomeIntent() {
            Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
            intent.setComponent(mTopComponent);
            if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                intent.addCategory(Intent.CATEGORY_HOME);
            }
            return intent;
        }
    

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容