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

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

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

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

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

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()。

解析SyetemServer进程

我们先来查看SystemServer的main函数:

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

SystemServer#main()

public static void main(String[] args) {

new SystemServer().run(); //1

}

注释1处main函数中只调用了SystemServer的run函数。

SystemServer#run()

private void run() {

System.loadLibrary(“android_servers”);//1

mSystemServiceManager = new SystemServiceManager(mSystemContext);//2

LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

try {

Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, “StartServices”);

startBootstrapServices();//3

startCoreServices();//4

startOtherServices();//5

} catch (Throwable ex) {

Slog.e(“System”, “******************************************”);

Slog.e(“System”, “************ Failure starting system services”, ex);

throw ex;

} finally {

Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

}

}

注释1处加载了libandroid_servers.so。

注释2处创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。启动系统的各种服务。

注释3中的startBootstrapServices函数中用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。

注释4处的函数中则启动了BatteryService、UsageStatsService和WebViewUpdateService。

注释5处的startOtherServices函数中则启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类为SystemService。

从注释3、4、5的函数可以看出,官方把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务,其中其他服务为一些非紧要和一些不需要立即启动的服务。系统服务大约有80多个,这里列出部分系统服务以及它们的作用:

最后

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。

最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司19年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

【延伸Android必备知识点】

【Android部分高级架构视频学习资源】

**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-jdjjOOZC-1713437417773)]

【算法合集】

[外链图片转存中…(img-LTP3BRyL-1713437417773)]

【延伸Android必备知识点】

[外链图片转存中…(img-udHMryTZ-1713437417774)]

【Android部分高级架构视频学习资源】

**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-8mJAlmWc-1713437417774)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值