0%

Android启动分析

https://www.jianshu.com/p/75039ea24937

v2-3733726e1c63b8fe74a2aecfd9bbd17f_1440w.webp

bootloader

bootloader程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,bootloader可以根据配置参数或者输入数据设置内核。

Kernel

kernel开始启动时,设置缓存、被保护存储器、计划列表,加载驱动。
当kernel完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程。

Init进程初始化

1
2
3
4
5
6
adb shell ps | grep 'init\|zygote'                                                                                                                                  0|1 ✘  14:07:25  

USER PID PPID VSZ RSS WCHAN ADDR S NAME
root 1 0 10967988 4108 0 0 S init
root 825 1 14869212 91388 0 0 S zygote64
root 826 1 1820048 36980 0 0 S zygote
  • system/core/init/main.cpp 入口
  • system/core/init/first_stage_init.cpp FirstStageMain,第一阶段,挂载系统文件
  • system/core/init/selinux.cpp SetupSelinux,第二阶段,
  • system/core/init/init.cpp SecondStageMain,第三阶段,初始化 property 服务,解析执行 rc 配置文件

Zygote进程

.rc 文件是配置文件,是由 Android 初始化语言(Android Init Language)编写的脚本,这里直接跟看下 system/core/rootdir/init.zygote64.rc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
# NOTE: If the wakelock name here is changed, then also
# update it in SystemSuspend.cpp
onrestart write /sys/power/wake_lock zygote_kwl
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart media.tuner
onrestart restart netd
onrestart restart wificond
task_profiles ProcessCapacityHigh
critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

  • frameworks/base/core/jni/AndroidRuntime.cpp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
    return;
    }
    // zygote 什么也不做
    onVmCreated(env);

    // 调用 com.android.internal.os.ZygoteInit 的 main方法

    JniInvocation Init
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    bool JniInvocationInit(struct JniInvocationImpl* instance, const char* library_name) {
    ...
    // 找到libart.so
    library_name = JniInvocationGetLibrary(library_name, buffer);
    // dlopen libart.so
    DlLibrary library = DlOpenLibrary(library_name);
    // 找到 3个 libart.so 中JNI符号
    DlSymbol JNI_GetDefaultJavaVMInitArgs_ = FindSymbol(library, "JNI_GetDefaultJavaVMInitArgs");
    if (JNI_GetDefaultJavaVMInitArgs_ == NULL) {
    return false;
    }

    DlSymbol JNI_CreateJavaVM_ = FindSymbol(library, "JNI_CreateJavaVM");
    if (JNI_CreateJavaVM_ == NULL) {
    return false;
    }

    DlSymbol JNI_GetCreatedJavaVMs_ = FindSymbol(library, "JNI_GetCreatedJavaVMs");
    if (JNI_GetCreatedJavaVMs_ == NULL) {
    return false;
    }
    // set param to JniInvocationImpl instance
    instance->jni_provider_library_name = library_name;
    instance->jni_provider_library = library;
    instance->JNI_GetDefaultJavaVMInitArgs = (jint (*)(void *)) JNI_GetDefaultJavaVMInitArgs_;
    instance->JNI_CreateJavaVM = (jint (*)(JavaVM**, JNIEnv**, void*)) JNI_CreateJavaVM_;
    instance->JNI_GetCreatedJavaVMs = (jint (*)(JavaVM**, jsize, jsize*)) JNI_GetCreatedJavaVMs_;

    return true;
    }

JNIEnv是一个结构体,定义在jni.h 中,实际的实现在art/runtime/jni/jni_internal.cc,主要作用是调用jni中提供的方法。

1
JNIEnv* env; 

startVm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
...
// 创建runtime,这里的runtime是art中的runtime
if (!Runtime::Create(options, ignore_unrecognized)) {
return JNI_ERR;
}

// 加载 /etc/public.libraries.txt 中的so
android::InitializeNativeLoader();

Runtime* runtime = Runtime::Current();
// link class,string,field
// 注册核心类的jni RegisterRuntimeNativeMethods(env);
// 缓存类对象 WellKnownClasses::Init(env);
// 设置类的权限 art::hiddenapi::InitializeCorePlatformApiPrivateFields();
// 初始化线程组
// 创建系统类加载器,并且给java 线程和native 线程设置了 classloader,这个classloader为 PathClassLoader
// 开启守护线程 StartDaemonThreads(); 调用了java中的Deamons
bool started = runtime->Start();
if (!started) {
delete Thread::Current()->GetJniEnv();
delete runtime->GetJavaVM();
LOG(WARNING) << "CreateJavaVM failed";
return JNI_ERR;
}

*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;



void LibraryNamespaces::Initialize() {

for (const std::string& soname : android::base::Split(preloadable_public_libraries(), ":")) {
//dlopen
void* handle = OpenSystemLibrary(soname.c_str(), RTLD_NOW | RTLD_NODELETE);
LOG_ALWAYS_FATAL_IF(handle == nullptr,
"Error preloading public library %s: %s", soname.c_str(), dlerror());
}
}

Runtime Create

1
2
3
4
5
6
7
8
9
10
11
12
13
bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
...
instance_ = new Runtime;
...
// init 代码很长
if (!instance_->Init(std::move(runtime_options))) {
instance_ = nullptr;
return false;
}
return true;
}


ZygoteInit main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public class ZygoteInit {
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;

// Mark zygote start. This ensures that thread creation will throw
// an error.
// 设置不可以创建线程,为了节省资源
ZygoteHooks.startZygoteNoThreadCreation();


Runnable caller;
try {

RuntimeInit.preForkInit(); // 开启ddms

if (!enableLazyPreload) {
// 预加载
preload(bootTimingsTraceLog);

}

// gc回收,这样fork的进程内存会小
gcAndFinalize();

Zygote.initNativeState(isPrimaryZygote);

// 可以创建线程了
ZygoteHooks.stopZygoteNoThreadCreation();
// 启动一个服务,这里提前创建是因为fork完成后,下面的代码会同时走
// ,所以fork后根据pid == 0 判断是否子进程,如果是,则close zygoteServer
// 但是这里有优化空间,可以根据pid==0来判断是否创建zygoteServer
zygoteServer = new ZygoteServer(isPrimaryZygote);

if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}

Log.i(TAG, "Accepting command socket connections");

// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}

// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
static void preload(TimingsTraceLog bootTimingsTraceLog) {

beginPreload(); // 部分类的加载和缓存

preloadClasses();//预加载这个文件中的class /system/etc/preloaded-classes

cacheNonBootClasspathClassLoaders(); //加载3个jar包

preloadResources(); // 预加载资源

nativePreloadAppProcessHALs();

maybePreloadGraphicsDriver();

preloadSharedLibraries(); //预加载3个so

preloadTextResources(); // textview 多语言和字体

WebViewFactory.prepareWebViewInZygote(); //加载webviewchromium_loader so
endPreload();
warmUpJcaProviders(); // 提前注册provider

}
}

system_server进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class ZygoteInit {
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {


try {

/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 子进程关闭socket
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}

return null;
}


private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {


if (parsedArgs.mInvokeWith != null) {
// app_process 启动一个nick_name进程
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);

} else {
ClassLoader cl = getOrCreateSystemServerClassLoader();
if (cl != null) {
Thread.currentThread().setContextClassLoader(cl);
}

//
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}

/* should never reach here */
}
}

这里返回的是一个Runnable,run中执行 com.android.server.SystemServer的main方法
同样如果是普通应用,Runnable中执行 android.app.ActivityThread的main方法

Zygote loop

相关类:

  • ZygoteProcess
  • Process
  • ProcessList
  • ZygoteServer
  • ZygoteConnect

其他

tmpfs,临时文件系统,是一种基于内存的文件系统,_tmpfs_可以使用RAM,但它也可以使用swap分区来存储。

mount解析:
https://blog.csdn.net/m0_38022615/article/details/106811680
https://blog.csdn.net/qq_19923217/article/details/81193579
mknod 函数用于创建各种类型的文件,包括普通文件、特殊文件以及设备文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Filesystem        1K-blocks     Used Available Use% Mounted on
/dev/block/dm-6 843672 841088 0 100% /
tmpfs 3882544 1516 3881028 1% /dev
magisk 3882544 4244 3878300 1% /dev/zisghzhbiibd
tmpfs 3882544 0 3882544 0% /mnt
/dev/block/dm-7 367392 366292 0 100% /system_ext
/dev/block/dm-8 2680860 2672836 0 100% /product
/dev/block/dm-9 516808 515228 0 100% /vendor
/dev/block/dm-10 40260 40136 0 100% /vendor_dlkm
tmpfs 3882544 140 3882404 1% /apex
/dev/block/dm-42 115621972 74044536 41446364 65% /data
/dev/block/dm-41 21448 21420 0 100% /apex/com.android.tethering@340913030
/dev/block/dm-39 23540 23508 0 100% /apex/com.android.media.swcodec@340922012
/dev/block/dm-38 776 748 12 99% /apex/com.android.ipsec@340914000
/dev/block/dm-40 4312 4280 0 100% /apex/com.android.adbd@340912002
/dev/block/dm-37 1304 1272 8 100% /apex/com.android.ondevicepersonalization@340821000
/dev/block/dm-35 15540 15508 0 100% /apex/com.android.cellbroadcast@340914000
/dev/block/dm-36 23028 22976 0 100% /apex/com.android.adservices@340915050
/dev/block/dm-34 7528 7496 0 100% /apex/com.android.neuralnetworks@340818110
/dev/block/loop14 47632 47604 0 100% /apex/com.android.vndk.v33@1
/dev/block/loop12 22764 22732 0 100% /apex/com.android.btservices@331716000
/dev/block/dm-29 4260 4228 0 100% /apex/com.android.media@340922012
/dev/block/dm-32 8276 8244 0 100% /apex/com.android.wifi@340913010
/dev/block/dm-30 10344 10312 0 100% /apex/com.android.mediaprovider@340919000
/dev/block/dm-27 3288 3256 0 100% /apex/com.android.os.statsd@340912000
/dev/block/dm-24 2592 2564 0 100% /apex/com.android.uwb@340818112
/dev/block/dm-25 9032 9004 0 100% /apex/com.android.extservices@340818110
/dev/block/dm-26 48400 48356 0 100% /apex/com.android.art@340915062
/dev/block/loop21 5352 5320 0 100% /apex/com.android.compos@1
/dev/block/dm-23 18640 18608 0 100% /apex/com.android.permission@340916010
/dev/block/dm-20 1888 1860 0 100% /apex/com.android.conscrypt@340818112
/dev/block/dm-21 784 756 12 99% /apex/com.android.tzdata@331910000
/dev/block/loop27 1616 1588 0 100% /apex/com.google.mainline.primary.libs@331434000
/dev/block/dm-19 4020 3992 0 100% /apex/com.android.resolv@340912000
/dev/block/dm-18 3588 3560 0 100% /apex/com.android.appsearch@340913000
/dev/block/dm-15 6228 6192 0 100% /apex/com.google.mainline.primary.libs@340941000
/dev/block/loop29 8028 7992 0 100% /apex/com.android.runtime@1
/dev/block/loop31 232 96 132 43% /apex/com.android.apex.cts.shim@1
/dev/block/loop30 141052 140952 0 100% /apex/com.google.pixel.camera.hal@810385117
/dev/block/loop32 36980 36948 0 100% /apex/com.android.i18n@1
/dev/block/dm-33 232 104 124 46% /apex/com.android.scheduling@340818110
/dev/block/dm-13 716 688 16 98% /apex/com.android.sdkext@340912010
/dev/block/loop35 91324 91280 0 100% /apex/com.android.virt@1
worker 3882544 0 3882544 0% /system/bin
/dev/fuse 115621972 74044536 41446364 65% /storage/emulated

rc文件:https://blog.51cto.com/u_16099228/6953501
selinux: https://www.php.cn/faq/500855.html

问题