Android源码-Android系统启动源码分析

Android系统启动源码分析

*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

解读Android的源码可以让我们更好的学习系统的优秀源码,以及google工程师对于一个程序的是如何实现的,从源码的分析也可以强化我们的编程思想.

引导

Android系统启动流程源码分析,基于Android5.1(个人比较喜欢这个版本的源码,因为改动比较大)

Android系统是基于linux内核的,所以在Android启动的时候会先去加载linux内核,内核启动的时候会去加载各种驱动以及数据结构等,然而,Android的第一个进程是初始化进程(init).

进程是由C代码实现的,即init.c;所以我们先从init.c开始阅读.由于init.c文件在Android源码中是有很多个的,我们需要阅读的是内核core的init文件,注意包名不要错误.

1.init.c的main函数:

《Android源码-Android系统启动源码分析》
在C语言中,main方法是函数的入口,我们先从main函数开始;由于是分析代码,所以我会把不需要的部分的代码删除,仅留下部分作为例子

int main(int argc, char **argv)
{

    //step1 创建必要的文件夹 , 权限分配 7代表可读可写可执行  5代表可读可执行不可写  挂载磁盘
    mkdir("/dev", 0755);
    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");

        //step2 初始化代码 包括日志初始化 配置文件初始化 以及硬件层初始化
    klog_init();
    property_init();


        //setp3 需要注意的一个初始化是init.rc配置文件的初始化   此处插入init.rc解读 详细请跳转  2.init.rc解读
    init_parse_config_file("/init.rc");

        //setp4 后续是很多的队列等待,等待初始化的完成,以及一些初始化失败的操作代码
    action_for_each_trigger("early-init", action_add_queue_tail);
    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");


    return 0;
}

2.init.rc解读 init.rc是linux系统下的一个启动配置文件,在android中的主要工作如下

《Android源码-Android系统启动源码分析》
setp1 文件系统的初始化和写入,变更权限等

    mkdir /sys/fs/cgroup/memory 0750 root system
    mount cgroup none /sys/fs/cgroup/memory memory
    write /sys/fs/cgroup/memory/memory.move_charge_at_immigrate 1
    chown system system /sys/kernel/ipv4/tcp_rmem_max

setp2 服务的启动,如下实例是一个大家比较熟悉的服务,网络模块服务启动,此项初始化了socket的网络通信

 Daemon processes to be run by init.
    service netd /system/bin/netd
    class main
    socket netd stream 0660 root system
    socket dnsproxyd stream 0660 root inet
    socket mdns stream 0660 root system
    socket fwmarkd stream 0660 root inet

setp3 重点服务讲解,孵化器服务

 service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote  //重点注意代码
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm

服务器服务zygote,进程的出现都是有孵化器完成的,也就是说孵化器进程是母进程

但是比较奇怪的是并没有在这个文件中出现直接启动的服务器进程的服务呢?这个就比较麻烦啦 哈哈

好好想一下,文件中既然有提到,onrestart restart zygote,从java的思想出发的话,这个文件里面一定是导入了服务器进程的包的,那么我们看一下文件的关联文件有哪些吧

 import /init.environ.rc
 import /init.usb.rc
 import /init.${ro.hardware}.rc
 import /init.${ro.zygote}.rc
 import /init.trace.rc

在文件的顶头会发现有一个import /init.${ro.zygote}.rc的文件关联,那么去找一下这个文件吧,搜索这个文件会发现有好几个,因为操作系统的位数分为了四个,但是其中内容都是一样的,细微差距就是app_process的路径文件夹名字会不一样,不过都指向同一个路径
《Android源码-Android系统启动源码分析》
如下:

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

**setp4 在这个服务中,可以看到路径是在app_process,看一下这个路径中的文件,只有一个文件**App_main.cpp,这个C++文件就是孵化器进程了
这次是一个C++文件,C++和C语言一样,入口函数都是main函数

3.孵化器App_main.cpp解读:

《Android源码-Android系统启动源码分析》
int main(int argc, char* const argv[])
{
//step1 忽略一些参数初始化方法

        //step2 AppRuntime为Android的运行时对象,下面代码是初始化了一个Android运行时环境
        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));


        //step3 初始化一些重要参数,后续对参数判断,参数初始化的时候会跳过第一个参数及父级路径
        bool zygote = false;
        bool startSystemServer = false;
        bool application = false;
        String8 niceName;
        String8 className;

        //step4 现在开始启动android的代码,com.android.internal.os.ZygoteInit
        //看到这样的是不是很熟悉啦,此类为android的孵化器进程
        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args);
        } else if (className) {
            runtime.start("com.android.internal.os.RuntimeInit", args);
        } else {
            fprintf(stderr, "Error: no class name or --zygote supplied.\n");
            app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
        }
    }

4.java孵化器类ZygoteInit.java解读:

《Android源码-Android系统启动源码分析》
step1 package com.android.internal.os;此类所在包

step2 对于java代码而言就没有什么main函数了,我们要从构造方法开始看

/**
 * Class not instantiable.
 * 比较尴尬 不给调用
 */
private ZygoteInit() {
}

孵化器的类是一个私有的构造方法,是不允许我们直接实例的类,那么按照常规的java代码套路的话,一般是有一个静态方法去创建他或者直接获得一个实例的,
但是找了一下,居然没有,哈哈!但很是意外的发现有一个main方法:

step3 main方法解读

    public static void main(String argv[]) {

            //在2.3的android\源码中是有一个运行时设置堆内存大小的,不过貌似被取消了

        try {
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

           /*
           *值得提醒一下的是,google的工程师在写代码的时候会有很多的逻辑判断
           *系统级别的程序代码就是严谨
           */

           //孵化器的socket注册
            registerZygoteSocket(socketName);

           /**
           *static void preload()
           *从命名可以看出这个方法是用作预加载的
           *预加载中内容比较多,也比较重要,下面会详细介绍
           *跳转 5.预加载preload();
           */
            preload();

            // Do an initial gc to clean up after startup
            //需要强调的一点是,java的回收机制虽然不是你乎他他就会来的
            //但是可以看到系统在做大量的IO操作的前后都会主动地去呼叫gc,可以借鉴为一个习惯
            gc();


                    //重点启动服务
            if (startSystemServer) {
                //跳转 6.启动Android系统服务介绍
                startSystemServer(abiList, socketName);
            }

        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (RuntimeException ex) {

        }
    }

5.预加载preload();

step1 方法内容

    static void preload() {
            Log.d(TAG, "begin preload");
            preloadClasses();
            preloadResources();
            preloadOpenGL();
            preloadSharedLibraries();
            // Ask the WebViewFactory to do any initialization that must run in the zygote process,
            // for memory sharing purposes.
            WebViewFactory.prepareWebViewInZygote();
            Log.d(TAG, "end preload");
        }

step2 preloadClasses()预加载类说明
《Android源码-Android系统启动源码分析》
/**
*从配置文件PRELOADED_CLASSES = “/system/etc/preloaded-classes”读取需要加载的类
*标准的JAVA的IO读取操作
*每次读取一行,读取到后进行反射加载类
*删掉大部分代码.留下核心部分
*在android5.1中这个配置文件是有3010行
*/
《Android源码-Android系统启动源码分析》
private static void preloadClasses() {

        is = new FileInputStream(PRELOADED_CLASSES);

        try {
            BufferedReader br
                = new BufferedReader(new InputStreamReader(is), 256);
            while ((line = br.readLine()) != null) {

                try {

                    Class.forName(line);

                } catch (ClassNotFoundException e) {

                } catch (UnsatisfiedLinkError e) {

                } catch (Throwable t) {

                }
            }

        } catch (IOException e) {

        } finally {
                //加载
           runtime.preloadDexCaches();
        }
    }

step3 preloadResources()加载资源,这个方法比较简单没什么好说的

 private static void preloadResources() {
    final VMRuntime runtime = VMRuntime.getRuntime();

    Debug.startAllocCounting();
    try {
        System.gc();
        runtime.runFinalizationSync();
        mResources = Resources.getSystem();
        mResources.startPreloading();
       //load资源数据
        mResources.finishPreloading();
    } catch (RuntimeException e) {
        Log.w(TAG, "Failure preloading resources", e);
    } finally {
        Debug.stopAllocCounting();
    }
}

step4 preloadOpenGL()方法,加载opengl相关,opengl是一个开源组织维护的,加载的话确实就是和java依赖库一样简单,没什么好解释的

private static void preloadOpenGL() {
    if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
        EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
    }
}

step5 preloadSharedLibraries()加载依赖库

 private static void preloadSharedLibraries() {
    Log.i(TAG, "Preloading shared libraries...");
    System.loadLibrary("android");
    System.loadLibrary("compiler_rt");
    System.loadLibrary("jnigraphics");
}

step6 WebViewFactory.prepareWebViewInZygote()浏览器作为APP中一个比较特殊的应用.这里就不详解

 public static void prepareWebViewInZygote() {
    try {
            //加载浏览器内核
        System.loadLibrary("webviewchromium_loader");
        long addressSpaceToReserve =
                SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY,
                CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES);
        sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);
    } catch (Throwable t) {

    }
}

6.启动Android系统服务介绍

step1 方法声明

 private static boolean startSystemServer(String abiList, String socketName)
                    throws MethodAndArgsCaller, RuntimeException {
               //初始化参数的代码(太多,不贴代码了)
               /**
               * "com.android.server.SystemServer"
               *参数初始化的时候有一个比较抢眼的参数SystemServer
               */
                try {
                /**
                *args参数中封装了"com.android.server.SystemServer"这个参数
                */
                    parsedArgs = new ZygoteConnection.Arguments(args);
                    /* Request to fork the system server process */

                    //这个方法中可以看到fork\出了一个系统进程
                    pid = Zygote.forkSystemServer(
                            parsedArgs.uid, parsedArgs.gid,
                            parsedArgs.gids,
                            parsedArgs.debugFlags,
                            null,
                            parsedArgs.permittedCapabilities,
                            parsedArgs.effectiveCapabilities);
                } catch (IllegalArgumentException ex) {
                    throw new RuntimeException(ex);
                }

                /* For child process */
                if (pid == 0) {
                    if (hasSecondZygote(abiList)) {
                        waitForSecondaryZygote(socketName);
                    }
                    //在系统进程完成之后处理剩下的一些子进程
                    handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

7.SystemServer分析

step1 类声明和构造说明
《Android源码-Android系统启动源码分析》

public final class SystemServer//此类被声明了为一个最终类,不可改变,公开访问

public SystemServer() {
    // Check for factory test mode.//只是做了模式检测
    mFactoryTestMode = FactoryTest.getMode();
}

在Android2.3的源码中,SystemServer类还包含了两个内部类,但是在5.1的版本中已经把两个内部类合并了(SensorService.cpp中),有兴趣的可以追溯一下2.3的源码

step2 main方法分析

public static void main(String[] args) {
    new SystemServer().run();
    //在main方法中只是调用了构造方法和run方法
}

step3 run方法分析

private void run() {
    //时间初始化
    if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
        Slog.w(TAG, "System clock is before 1970; setting to 1970.");
        SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
    }
    //looper的初始化,handler处理的时候不需要自己初始化一个looper就是因为系统已经为主线程准备了looper
    Looper.prepareMainLooper();

    // Initialize native services
    /**
    *加载了一个so库文件,然后调用了init的jni方法
    *libandroid_servers.so
    *可以在目录中找到这个文件的so库阅读init方法
    */
    System.loadLibrary("android_servers");
    nativeInit();

    // Start services.重点放到  第九点说明
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    }

    // Loop forever.
    //到此处说明已经开始轮训去做消息处理了 完成
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

8.android_servers库源码

step1 源代码查找
路径:F:\Android5\android5.1\frameworks\base\services\core\jni
《Android源码-Android系统启动源码分析》

step2 nativeInit方法

static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }
}

该方法主要调用了SensorService::instantiate(),实例了SensorService对象

step3 SensorService阅读
《Android源码-Android系统启动源码分析》
路径如下:F:\Android5\android5.1\frameworks\native\services\sensorservice
因为SensorService启动后执行的就是onFirstRef方法,所以我们直接看这个方法

void SensorService::onFirstRef()
{
//硬件的初始化
SensorDevice& dev(SensorDevice::getInstance());

        //looper的初始化
        mLooper = new Looper(false);
        //运行SensorService
        run("SensorService", PRIORITY_URGENT_DISPLAY);

}

9 后续启动

step1 硬件完成后

startBootstrapServices();
startCoreServices();
startOtherServices();

step2 startBootstrapServices()

 private void startBootstrapServices() {

    Installer installer = mSystemServiceManager.startService(Installer.class);

    // Activity manager runs the show.Activity相关启动
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);

    //电源相关启动
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    mActivityManagerService.initPowerManagement();

   //显示相关启动
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

  //应用管理器
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();

    //服务管理器
    ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());

    // Initialize attribute cache used to cache resources from packages.
    AttributeCache.init(mSystemContext);

    // Set up the Application instance for the system process and get started.
    mActivityManagerService.setSystemProcess();
}

step3 startCoreServices();
这一段google工程师注释很详细了就不多解释了
private void startCoreServices() {
// Manages LEDs and display backlight.
mSystemServiceManager.startService(LightsService.class);

    // Tracks the battery level.  Requires LightService.
    mSystemServiceManager.startService(BatteryService.class);

    // Tracks application usage stats.
    mSystemServiceManager.startService(UsageStatsService.class);
    mActivityManagerService.setUsageStatsManager(
            LocalServices.getService(UsageStatsManagerInternal.class));
    // Update after UsageStatsService is available, needed before performBootDexOpt.
    mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

    // Tracks whether the updatable WebView is in a ready state and watches for update installs.
    mSystemServiceManager.startService(WebViewUpdateService.class);
}

step4 startOtherServices();
此处代码量非常大,认真慢慢来

private void startOtherServices() {
   //前面变量初始化就删掉啦,下面代码也一样,留下重要部分
    try {
            //功能性服务初始化
         //电话功能 此try内大部分为相似,值得注意的是,在这部分在会掉过蓝牙服务
        telephonyRegistry = new TelephonyRegistry(context);
        ServiceManager.addService("telephony.registry", telephonyRegistry);
    } catch (RuntimeException e) {

    }

     //此处基本上为手机对于我们可见部分的服务启动,比如UI

    try {
        wm.displayReady();
    } catch (Throwable e) {
        reportWtf("making display ready", e);
    }


      //系统设置服务初始化,比如wifi什么的,通知什么的
            mSystemServiceManager.startService("com.android.server.wifi.RttService");

        //launcher服务
        mSystemServiceManager.startService(LauncherAppsService.class);
    }

      //必要的系统配置
    Configuration config = wm.computeNewConfiguration();


   //可授权第三方的APP启动了,值得注意的是ActivityManagerService的systemReady()方法
    mActivityManagerService.systemReady(new Runnable() {
        @Override
        public void run() {
            Slog.i(TAG, "Making services ready");
            mSystemServiceManager.startBootPhase(
                    SystemService.PHASE_ACTIVITY_MANAGER_READY);

            try {
                mActivityManagerService.startObservingNativeCrashes();
            } catch (Throwable e) {
                reportWtf("observing native crashes", e);
            }

            Slog.i(TAG, "WebViewFactory preparation");
            WebViewFactory.prepareWebViewInSystemServer();

             //此处忽略各种判断捕获
        }
    });
}

10.ActivityManagerService.java

《Android源码-Android系统启动源码分析》
路径依然还是frameworks下
step1 systemReady()方法

public void systemReady(final Runnable goingCallback) {
    //在这个方法中会发现很多代码都有synchronized在修饰
    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;
        }

       //安全检查,就是锁屏输密码
        updateCurrentProfileIdsLocked();

        if (!mDidUpdate) {
            if (mWaitingUpdate) {
                return;
            }
            final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
            mWaitingUpdate = deliverPreBootCompleted(new Runnable() {
                public void run() {
                   //记载各种组件
                    systemReady(goingCallback);
                }
            }, doneReceivers, UserHandle.USER_OWNER);

        }

        mAppOpsService.systemReady();
        mSystemReady = true;
    }



    //到这里的时候 系统已经万全准备好了
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
        SystemClock.uptimeMillis());

         //锁定栈顶的activity,至此,已经是到了手机解锁的界面了
        mStackSupervisor.resumeTopActivitiesLocked();
        sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
    }
}

总结

对于Android的启动源码呢,涉及到了很多的东西,方方面面,我可能讲的不是很到位,还是各位慢慢吸收理解.多多支持.

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/ynztlxdeai/article/details/69675754
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞