之前用Github 的git page 搭配 Hexo来写文章,非常的繁琐。现在改用来记录自己学习的点滴。欢迎各位观看文章的朋友可以一起学习。
目前我所下载的Android系统源码版本为android-7.1.0_r7不算太旧。目前市场上的大部分系统解读的书籍,基本都是在android4.0到5.0之间,大部分没有到5.0。本人也是看书之后,发现新旧源码还是有较大差别的。
启动配置文件读取
启动之初,会读取一个文件 init.rc 这个文件是最初进行读取的配置文件,作用
- 初始化
- 生成设备文件夹
- 初始化应用服务孵化器 Zygote,在代码中有所体现。如图
文件地址system/core/rootdir/init.rc
根据上面代码,应该可以看出,在系统读取这个文件并导入相关的孵化器的初始化文件,其中 ro.zygote 应该为系统加载读取这个文件时传入的参数,这个参数应该是系统启动时,根据硬件的一些特殊信息生成的。
具体加载了什么文件? 这里有个列表:
在上面的文件目录中可以看出,在执行import 的代码时,真正导入的文件便是框出的几个文件,根据不同的硬件基础生成的不同文件。选取init.zygote64.rc进行观察。
这个文件中的配置命令的语法我还没具体搞清楚。但是,不凡可以进行大胆的猜想。在红色框中框出的,貌似应该是个可执行文件,根据以往在Ubuntu系统的命令行程序中的写法,的确十分相似。那么这个 app_process的可执行文件是在哪里生成的?(在这里,如果是小白,极力推荐去买本书,参考的看代码,不然你根本找不到,也摸不清来龙去脉。)
frameworks/bash/cmds/app_process/app_main.cpp
可以先看看 Android.mk编译配置文件,其中就是如何生成上面所讲的app_process命令的过程。
# 定位编译根目录
LOCAL_PATH:= $(call my-dir)
# This is a list of libraries that need to be included in order to avoid
# bad apps. This prevents a library from having a mismatch when resolving
# new/delete from an app shared library.
# See b/21032018 for more details.
app_process_common_shared_libs := \
libwilhelm \
# 清空之前编译的缓存变量
include $(CLEAR_VARS)
# 本地需要编译的C++文件
LOCAL_SRC_FILES:= \
app_main.cpp
LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
LOCAL_SHARED_LIBRARIES := \
libdl \
libcutils \
libutils \
liblog \
libbinder \
libnativeloader \
libandroid_runtime \
$(app_process_common_shared_libs) \
LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
# 生成动态库模块名称
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
# !!!!!这里就是关键!!!!!生成32位和64位的Zygote初始化可执行命令文件。
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
# 生成可执行.so动态库文件,如果有点印象,在app的jni开发中经常会使用到BUILD_SHARE_LIBRARY。
# 下面的也可以这么理解了。
include $(BUILD_EXECUTABLE)
# Create a symlink from app_process to app_process32 or 64
# depending on the target configuration.
include $(BUILD_SYSTEM)/executable_prefer_symlink.mk
# Build a variant of app_process binary linked with ASan runtime.
# ARM-only at the moment.
ifeq ($(TARGET_ARCH),arm)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
app_main.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog \
libbinder \
libandroid_runtime \
$(app_process_common_shared_libs) \
LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
LOCAL_LDFLAGS := -ldl -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
LOCAL_CPPFLAGS := -std=c++11
LOCAL_MODULE := app_process__asan
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
LOCAL_SANITIZE := address
LOCAL_CLANG := true
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
include $(BUILD_EXECUTABLE)
endif # ifeq($(TARGET_ARCH),arm)
那么到这里,肯定是要看看这个app_main.cpp文件中的具体代码是干什么的了。
如果是可执行文件,自然肯定会有main函数
int main(int argc, char* const argv[]){
...代码省略
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
//读取在执行该命令时,给出的参数
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
//重点,注意!!!
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; //初始化Android系统服务的配置
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
Vector args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) { //!!!!重点!!!!,设置配置参数
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
...代码省略
if (zygote) { // !!!!通过jni,C++代码调用具体的java类中的main函数。并传入参数
//在这里,孵化器的初始化工作才刚刚开始执行
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.");
return 10;
} //到这里,代码结束
}
上面的runtime.start("com.android.internal.os.ZygoteInit", args, zygote);个人觉得应该可以去看看,理解一下是如何调用com.android.internal.os.ZygoteInit这个类的main函数的。
AndroidRuntime.cpp文件的具体位置
frameworks/base/core/jni/AndroidRuntime.cpp
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
...代码省略
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */ //初始化java虚拟机环境,方便后面用jni调用java类的函数
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
char* slashClassName = toSlashClassName(className);
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//!!!!!这里便是孵化器ZygoteInit.java的main函数的调用方法了。
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 {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
根据上面最后的注释,执行完这个命令之后,孵化器的初始化工作就开始了。
接下来分析一下ZygoteInit.java的代码
一样,从main函数开始
public static void main(String argv[]) {
...省略代码
if (startSystemServer) {// 初始化系统服务,所有的子系统服务都从这里开始
startSystemServer(abiList, socketName);
}
}
这里需要注意的一个关键的地方,如下图:
这里的代码有些奇怪不同以往的代码编写方式,将Runnable用作异常在底层函数抛出,然后在抓取异常的时候,执行里面的run方法。在文章的最后截图中可以看到向上抛出的异常。
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
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); //进入到这个方法内部查看代码,可找到启动系统服务的入口
}
}
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
...省略代码
/*
* Pass the remaining arguments to SystemServer.
*/
//!!!!这句话关键,进入去看看
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
到这里,就会去执行SystemServer.java文件的main函数,初始化剩余的系统服务了。