Android笔记 从init到SystemServer

1.SystemServer介绍

android中PackageManagerService,WindowManagerService,ActivityManagerService等服务在这里被启动,android中各种大大小小的系统服务都源于SystemServer,(13、14、15行就是启动这些系统服务的方法)

frameworks/base/services/java/com/android/server/SystemServer.java

    public static void main(String[] args) {
        new SystemServer().run();
    }

    ...

    private void run() {
		...
        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            //123三个方法分别启动了系统中各种服务
            startBootstrapServices();//1
            startCoreServices();//2
            startOtherServices();//3
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        ...
	}

看看到底是哪里调到SystemServer的main方法的,带着这个目的开始出发

2.关于计算机开机方面的一些知识

计算机的启动流程:计算器上所有的软件包括系统都是放在硬盘上的,程序执行时需要将程序从硬盘读取到内存再加载到CPU来运行,当我们按下开机键的时候内存中什么都没有,需要将操作系统读取到内存中进而在CPU加载起来,完成这个工作的就是BIOS

BIOS:它是一组固化到计算机内主板上一个ROM芯片上的程序;理解:电脑的主板上有一个BIOS芯片,而BIOS程序就在其中

Linux:BIOS工作完以后,控制权交给操作系统,先加载kernel然后在加载操作系统第一个进程init进程

android:没有BIOS,替代BIOS的是Bootloader

总结android的开机流程应该是:上电->Bootloader加载kernel->init

3.代码分析

init进程的源码路径在/system/core/init/,而该进程的入口在

system/core/init/init.cpp

int main(int argc, char** argv) {
	...
    if (bootscript.empty()) {
        parser.ParseConfig("/init.rc");//解析init.rc
        parser.set_is_system_etc_init_loaded(
                parser.ParseConfig("/system/etc/init"));
        parser.set_is_vendor_etc_init_loaded(
                parser.ParseConfig("/vendor/etc/init"));
        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
    } else {
        parser.ParseConfig(bootscript);
        parser.set_is_system_etc_init_loaded(true);
        parser.set_is_vendor_etc_init_loaded(true);
        parser.set_is_odm_etc_init_loaded(true);
    }
	...
}

这里mian函数中解析了init.rc,当然除此之外,还做了很多重要的工作。因为我的目的是找到哪里调到SystemServer的main方法的,对于一些其他不作分析,后面也是一样,这里会直奔主题

system/core/rootdir/init.rc

# Copyright (C) 2012 The Android Open Source Project
#
# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.
#

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc //注意这里

...
on post-fs
    # Load properties from
    #     /system/build.prop,
    #     /odm/build.prop,
    #     /vendor/build.prop and
    #     /factory/factory.prop
    load_system_props
    # start essential services
    start logd
    start servicemanager //启动servicemanager
    start hwservicemanager
    start vndservicemanager
...

在init.rc中,需要注意的是第12行代码,这个ro.zygote会决定后面分析中读取的是那一个init.rc,而后启动了servicemanager,他是Binder机制中的"DNS服务器",它的源码在

frameworks/native/cmds/servicemanager/servicemanager.rc

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote//servicemanager每次重启zygote都会被restart
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

原本这段代码是写在init.rc中的,后面改到这里去了,可以看到在servicemanager 会去重启zygote,前面又说到注意ro.zygote,通过他可以知道读取的是那个zygote.rc,如果ro.zygote的值为zygote32的话,service zygote就会被定义在init.zygote32.rc,再来看看init.zygote32.rc

system/core/rootdir/init.zygote32.rc

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

可以看到启动service zygote实际上就是启动/system/bin/app_process模块,然后我们就去看看app_process做了什么事情,补充一点/system/bin/app_process指的是手机中的路径,并不是源码中的路径,就像前面的init.rc,解析的时候是/init.rc,这是手机中的路径,system/core/rootdir/init.rc的代码经过Android.mk模块编译后打包成软件进到手机里面就会存在根目录上了

system/core/rootdir/Android.mk

#######################################
# init.rc
include $(CLEAR_VARS)

LOCAL_MODULE := init.rc //生成模块的名字
LOCAL_SRC_FILES := $(LOCAL_MODULE) //代码路径,表示在当前路径
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) //生成路径在根目录下

include $(BUILD_PREBUILT)

接着继续分析app_process,先找到app_process在哪里编译出来的

frameworks/base/cmds/app_process/Android.mk

...
LOCAL_MODULE:= app_process
...

那么app_process的实现就在frameworks/base/cmds/app_process同路径的代码上

frameworks/base/cmds/app_process/app_main.cpp

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

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

调用runtime.start函数(6行),参数有ZygoteInit的类名,看看start怎么实现的,runtime是AppRuntime类,但是AppRuntime没有实现start函数,看看AppRuntime的父类AndroidRuntime

frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);//启动虚拟机

    ...

    char* slashClassName = toSlashClassName(className != NULL ? className : ""); //1
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V"); //2
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray); //3
    ...
}

5到12行代码,启动虚拟机;28行env->CallStaticVoidMethod就是典型的native framework调java framework的方法,其中参数startClass是在app_main.cpp传进来的"com.android.internal.os.ZygoteInit",startMeth是第22、23行所定义的main,也就是说,来到这里,下一步就是ZygoteInit的main方法了

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    public static void main(String argv[]) {
        ...
        try {
            ...
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
                ...
            }
        ...
    }
    
    private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) {
        ...
		
        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",//这个不正是我们梦寐以求的SystemServer吗
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);//<-------1
            ...
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs); //<-------2
        }

        return null;
    }
    
    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
            ...
        
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); //<---------3
            ...
    }
    
    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        ..
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); //<----4
    }

从main方法的第6行forkSystemServer中发现了一个String类型的数组args(第16行),为什么关注他,因为它里面(23行),有文章开头的目标SystemServer,跟踪他传递到哪里去了,在30行他转化成了parsedArgs,在42行传到handleSystemServerProcess在51他继续以parsedArgs.remainingArgs往下传到了zygoteInit方法(57行),这里继续传到RuntimeInit.applicationInit。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ...
        return findStaticMain(args.startClass, args.startArgs, classLoader);//<----
    }
    
    private static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            //加载mian函数
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
        ...
    }

继续跟踪RuntimeInit的applicationInit方法,他把前面穿进来的参数分解成了所需的类名args.startClass,继续往下传递给findStaticMain方法(第4行),第22行,通过反射加载了SystemServer的main方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值