Android-Framework学习笔记(三)SystemServer进程启动过程

注释1处调用Zygote的forkSystemServer,主要通过fork函数在当前进程创建一个子进程(也就是SystemServer进程),如果返回的pid 为0,也就是表示在新创建的子进程中执行的,则执行注释2处的handleSystemServerProcess,来看看handleSystemServerProcess是如何启动SystemServer进程的。

ZygoteInit#handleSystemServerProcess()

private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {

closeServerSocket(); //1

if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName); //2
}

if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
// If we have a non-null system server class path, we’ll have to duplicate the
// existing arguments and append the classpath to it. ART will handle the classpath
// correctly when we exec a new process.
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = “-cp”;
amendedArgs[1] = systemServerClasspath;
System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}

WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createSystemServerClassLoader(systemServerClasspath,
parsedArgs.targetSdkVersion);

Thread.currentThread().setContextClassLoader(cl);
}

/*

  • Pass the remaining arguments to SystemServer.
    */
    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); //3
    }

/* should never reach here */
}

注释1处SyetemServer进程是复制了Zygote进程的地址空间,因此也会得到Zygote进程创建的Socket,这个Socket对于SyetemServer进程没有用处,所以调用closeServerSocket()关闭它。
注释2如果你看Arguments封装函数,会发现parsedArgs.niceName=system_server,在这里调用Process.setArgV0()设置进程名为:system_server。
注释3由于parsedArgs.invokeWith属性默认为null,最后调用RuntimeInit.zygoteInit来进一步启动SystemServer。

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

RuntimeInit#zygoteInit()

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

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, “RuntimeInit”);
// 重定向Log输出
redirectLogStreams();
//初始化运行环境
commonInit();
//启动Binder线程池
nativeZygoteInit(); //1
//调用程序入口函数
applicationInit(targetSdkVersion, argv, classLoader); //2
}

注释1处调用nativeZygoteInit函数,一看函数的名称就知道调用Native层的代码,它是用来启动Binder线程池的。
注释2处调用了applicationInit函数启动应用程序。

Binder线程池启动过程

先看看启动Binder线程池。来查看nativeZygoteInit函数对应的JNI文件,如下所示。

frameworks/base/core/jni/AndroidRuntime.cpp

static const JNINativeMethod gMethods[] = {
{ “nativeFinishInit”, “()V”,
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ “nativeZygoteInit”, “()V”,
(void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
{ “nativeSetExitWithoutCleanup”, “(Z)V”,
(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};

通过JNI的gMethods数组,可以看出nativeZygoteInit函数对应的是JNI文件AndroidRuntime.cpp的com_android_internal_os_RuntimeInit_nativeZygoteInit函数:

AndroidRuntime#com_android_internal_os_RuntimeInit_nativeZygoteInit()


static AndroidRuntime* gCurRuntime = NULL;

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
mExitWithoutCleanup(false),
mArgBlockStart(argBlockStart),
mArgBlockLength(argBlockLength)
{

gCurRuntime = this;
}

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}

这里gCurRuntime是AndroidRuntime类型的指针,AndroidRuntime的子类AppRuntime在app_main.cpp中定义,我们来查看AppRuntime的onZygoteInit函数

frameworks/base/cmds/app_process/app_main.cpp

AppRuntime#onZygoteInit()

virtual void onZygoteInit()
{
sp proc = ProcessState::self();
ALOGV(“App process: starting thread pool.\n”);
proc->startThreadPool();//1
}

注释1处会调用ProcessState的startThreadPool函数。

frameworks/native/libs/binder/ProcessState.cpp

ProcessState#startThreadPool()

void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
//1
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}

支持Binder通信的进程中都有一个ProcessState类,它里面有一个mThreadPoolStarted 变量,来表示Binder线程池是否已经被启动过,默认值为false。在每次调用这个函数时都会先去检查这个标记,从而确保Binder线程池只会被启动一次。
注释1如果Binder线程池未被启动则设置mThreadPoolStarted为true,最后调用spawnPooledThread函数来创建线程池中的第一个线程,也就是线程池的main线程。

ProcessState#spawnPooledThread()

void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV(“Spawning new pooled thread, name=%s\n”, name.string());
sp t = new PoolThread(isMain);
t->run(name.string());//1
}
}

可以看到Binder线程为一个PoolThread。注释1调用PoolThread的run函数来启动一个新的线程。

PoolThread

class PoolThread : public Thread
{

protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);//1
return false;
}
const bool mIsMain;
};

PoolThread类继承了Thread类。注释1处会将调用IPCThreadState的joinThreadPool函数,将当前线程注册到Binder驱动程序中,这样我们创建的线程就加入了Binder线程池中,这样新创建的SyetemServer进程就支持Binder进程间通信了。

回到RuntimeInit#zygoteInit()的注释2。

RuntimeInit#applicationInit()

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {

// 初始化虚拟机环境
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}

// Remaining arguments are passed to the start class’s static main
invokeStaticMain(args.startClass, args.startArgs, classLoader); //1
}

注释1处applicationInit函数中主要调用了invokeStaticMain函数。

RuntimeInit#invokeStaticMain()

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;

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

Method m;
try {
// 获取main方法
m = cl.getMethod(“main”, new Class[] { String[].class }); //2
} 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);
}
// 判断修饰符
int modifiers = m.getModifiers(); //3
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);
}

/*

  • This throw gets caught in ZygoteInit.main(), which responds
  • by invoking the exception’s run() method. This arrangement
  • clears up all the stack frames that were required in setting
  • up the process.
    */
    throw new ZygoteInit.MethodAndArgsCaller(m, argv); //4
    }

注释1处传入的className就是com.android.server.SystemServer ,因此通过反射返回的cl为SystemServer类。
注释2获取main方法 。
注释3判断修饰符,必须是static而且必须是public类型。
注释4有点意思,做完这一切之后,将找到的main函数传入到MethodAndArgsCaller异常中并抛出该异常。辛苦辛苦各种初始化,各种变着法的调用,最后你居然给我抛个异常!先别急,这个异常在ZygoteInit#main()方法中捕获。这么做的作用是清除应用程序进程创建过程的调用栈。

ZygoteInit#main()函数见上一篇文章,我们这里再看一下框架:

public static void main(String argv[]) {
try {

startSystemServer(abiList, socketName);

} catch (MethodAndArgsCaller caller) {
caller.run(); //1
}
}

在注释1处调用了MethodAndArgsCaller的run函数。

MethodAndArgsCaller

public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;

/** argument array */
private final String[] mArgs;

public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}

public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs }); //1
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}

注释1处通过反射调用了com.android.server.SystemServer#main(String[] args)。至此,Zygote进程fork出SystemServer进程,并成功调用SystemServer#main()。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

最后

给大家送上我成功跳槽复习中所整理的资料,由于文章篇幅有限,所以只是把题目列出来了

image

image

image

**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-8f5brDIe-1711915429988)]

最后

给大家送上我成功跳槽复习中所整理的资料,由于文章篇幅有限,所以只是把题目列出来了

[外链图片转存中…(img-FDazBuoe-1711915429988)]

[外链图片转存中…(img-fxzVT6Sw-1711915429989)]

[外链图片转存中…(img-yAodB3M3-1711915429989)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值