Android上层是java,framework是java,native是c++,驱动是c 。连接起来的是jni,虚拟机
如借用的图所示,Android Runtime连接了framework和lib,包括两部分:core lib和虚拟机(5.1开始art完全取代dv)
android启动是从init.c开始的,而且init是android的第一个进程,zygot也是其fork的
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 17112 1304 SyS_epoll_ 0000000000 S /init
root 2 0 0 0 kthreadd 0000000000 S kthreadd
root 3 2 0 0 smpboot_th 0000000000 S ksoftirqd/0
root 5 2 0 0 worker_thr 0000000000 S kworker/0:0H
root 6 2 0 0 diag_socke 0000000000 S kworker/u16:0
root 512 1 6564 388 SyS_epoll_ 0000000000 S /sbin/healthd
root 513 1 18084 1164 binder_thr 0000000000 S /system/bin/performanceadjustor
nobody 516 1 16860 984 poll_sched 0000000000 S /system/bin/rmt_storage
root 517 2 0 0 worker_thr 0000000000 S kworker/7:1H
rfs 518 1 11260 804 poll_sched 0000000000 S /system/bin/tftp_server
这是坚果的,kthreadd应该就是zygote,坚果给重命名了。bin sbin system/bin是init进程fork出来的,PPID是1,其他都是zygote进程fork出来的,PPID是2。
1.init进程作为linux启动过程中的一个重要的进程,它主要负责文件系统的挂载,属性的初始化,各种配置的加载启动以及Action触发,Service的启动,而Zygote作为Java环境下的服务进程,也在Init.rc中进行了配置,而init进程是由main函数进行触发的
/system/core/init/init.c
int main(int argc, char **argv) 837{ ... 848 if (!strcmp(basename(argv[0]), "ueventd")) 849 return ueventd_main(argc, argv);//uevent 850 851 if (!strcmp(basename(argv[0]), "watchdogd")) 852 return watchdogd_main(argc, argv); 853 854 /* clear the umask */ 855 umask(0); 856 857 /* Get the basic filesystem setup we need put 858 * together in the initramdisk on / and then we'll 859 * let the rc file figure out the rest. 860 */ 861 mkdir("/dev", 0755); //挂在文件系统 862 mkdir("/proc", 0755); 863 mkdir("/sys", 0755); 864 865 mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); 866 mkdir("/dev/pts", 0755); 867 mkdir("/dev/socket", 0755); 868 mount("devpts", "/dev/pts", "devpts", 0, NULL); 869 mount("proc", "/proc", "proc", 0, NULL); 870 mount("sysfs", "/sys", "sysfs", 0, NULL); 871 872 /* indicate that booting is in progress to background fw loaders, etc */ 873 close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); 874 875 /* We must have some place other than / to create the 876 * device nodes for kmsg and null, otherwise we won't 877 * be able to remount / read-only later on. 878 * Now that tmpfs is mounted on /dev, we can actually 879 * talk to the outside world. 880 */ 881 open_devnull_stdio(); 882 klog_init(); //klog 初始化 883 property_init();//property 初始化 884 885 get_hardware_name(hardware, &revision); 886 887 process_kernel_cmdline();//执行kernel命令 888 889#ifdef HAVE_SELINUX 890 union selinux_callback cb; 891 cb.func_log = klog_write; 892 selinux_set_callback(SELINUX_CB_LOG, cb); 893 894 cb.func_audit = audit_callback; 895 selinux_set_callback(SELINUX_CB_AUDIT, cb); 896 897 INFO("loading selinux policy\n"); 898 if (selinux_enabled) { 899 if (selinux_android_load_policy() < 0) {//加载selinux policy 900 selinux_enabled = 0; 901 INFO("SELinux: Disabled due to failed policy load\n"); 902 } else { 903 selinux_init_all_handles();//se 初始化 904 } 905 } else { 906 INFO("SELinux: Disabled by command line option\n"); 907 } 908 /* These directories were necessarily created before initial policy load 909 * and therefore need their security context restored to the proper value. 910 * This must happen before /dev is populated by ueventd. 911 */ 912 restorecon("/dev"); 913 restorecon("/dev/socket"); 914#endif 915 916 is_charger = !strcmp(bootmode, "charger"); 917 918 INFO("property init\n"); 919 if (!is_charger) 920 property_load_boot_defaults(); //加载prop 921 922 INFO("reading config file\n"); 923 init_parse_config_file("/init.rc");//解析init.rc里面有zygote信息,各种service信息 ... 1026}
2.init.rc 起zygote。在手机目录能看到system/bin/app_process,--zygote --start-system-server是参数,在后续是决定是zygote还是非zygote模式的参数
/system/core/rootdir/init.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server 444 class main 445 socket zygote stream 660 root system 446 onrestart write /sys/android_power/request_state wake 447 onrestart write /sys/power/state on 448 onrestart restart media 449 onrestart restart netd
3.进入app_main.cpp的main函数
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]) 188{ 189 if (!LOG_NDEBUG) { ... 196 ALOGV("app_process main with argv: %s", argv_String.string());//log佐证起了app_process 197 } 198 199 AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); 200 // Process command line arguments 201 // ignore argv[0] 202 argc--; 203 argv++; 204 //这段注释解释的还是比较清楚,由传入的参数决定是zygote还是非zygote模式 205 // Everything up to '--' or first non '-' arg goes to the vm. 206 // 207 // The first argument after the VM args is the "parent dir", which 208 // is currently unused. 209 // 210 // After the parent dir, we expect one or more the following internal 211 // arguments : 212 // 213 // --zygote : Start in zygote mode 214 // --start-system-server : Start the system server. 215 // --application : Start in application (stand alone, non zygote) mode. 216 // --nice-name : The nice name for this process. 217 // 218 // For non zygote starts, these arguments will be followed by 219 // the main class name. All remaining arguments are passed to 220 // the main method of this class. 221 // 222 // For zygote starts, all remaining arguments are passed to the zygote. 223 // main function. 224 // 225 // Note that we must copy argument string values since we will rewrite the 226 // entire argument block when we apply the nice name to argv0. 227 // 228 // As an exception to the above rule, anything in "spaced commands" 229 // goes to the vm even though it has a space in it. 230 const char* spaced_commands[] = { "-cp", "-classpath" }; 231 // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s). ... 272 while (i < argc) {//不同参数的赋值,决定后续调用方向 273 const char* arg = argv[i++]; 274 if (strcmp(arg, "--zygote") == 0) { 275 zygote = true; 276 niceName = ZYGOTE_NICE_NAME; 277 } else if (strcmp(arg, "--start-system-server") == 0) { 278 startSystemServer = true; 279 } else if (strcmp(arg, "--application") == 0) { 280 application = true; 281 } else if (strncmp(arg, "--nice-name=", 12) == 0) { 282 niceName.setTo(arg + 12); 283 } else if (strncmp(arg, "--", 2) != 0) { 284 className.setTo(arg); 285 break; 286 } else { 287 --i; 288 break; 289 } 290 } ... 342 343 if (zygote) { 344 runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 345 } else if (className) { 346 runtime.start("com.android.internal.os.RuntimeInit", args, zygote); 347 } else { 348 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); 349 app_usage(); 350 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); 351 } 352}
传了不同的参数ZygoteInit和RuntimeInit
4. 进入AndroidRuntime.cpp的start函数
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const char* options) 807{ ... 837 /* start the virtual machine */ 838 JNIEnv* env; 839 if (startVm(&mJavaVM, &env) != 0) {//启动虚拟机 840 return; 841 } 842 onVmCreated(env);//释放资源,跟进去看就知道 843 844 /* 845 * Register android functions. 846 */ 847 if (startReg(env) < 0) { 848 ALOGE("Unable to register all android natives\n"); 849 return; 850 } 851 852 /* 853 * We want to call main() with a String array with arguments in it. 854 * At present we have two arguments, the class name and an option string. 855 * Create an array to hold them. 856 *///注释暴露了目标调用class 的main函数 857 jclass stringClass; 858 jobjectArray strArray; 859 jstring classNameStr; 860 jstring optionsStr; 861 862 stringClass = env->FindClass("java/lang/String"); 863 assert(stringClass != NULL); 864 strArray = env->NewObjectArray(2, stringClass, NULL); 865 assert(strArray != NULL); 866 classNameStr = env->NewStringUTF(className); 867 assert(classNameStr != NULL); 868 env->SetObjectArrayElement(strArray, 0, classNameStr); 869 optionsStr = env->NewStringUTF(options); 870 env->SetObjectArrayElement(strArray, 1, optionsStr); 871 872 /* 873 * Start VM. This thread becomes the main thread of the VM, and will 874 * not return until the VM exits. 875 */ 876 char* slashClassName = toSlashClassName(className); 877 jclass startClass = env->FindClass(slashClassName); 878 if (startClass == NULL) { 879 ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); 880 /* keep going */ 881 } else { 882 jmethodID startMeth = env->GetStaticMethodID(startClass, "main", 883 "([Ljava/lang/String;)V");//获取main函数 884 if (startMeth == NULL) { 885 ALOGE("JavaVM unable to find main() in '%s'\n", className); 886 /* keep going */ 887 } else { 888 env->CallStaticVoidMethod(startClass, startMeth, strArray);//调用main函数 889 890#if 0 891 if (env->ExceptionCheck()) 892 threadExitUncaughtException(env); 893#endif 894 } 895 } 896 free(slashClassName); 897 898 ALOGD("Shutting down VM\n"); 899 if (mJavaVM->DetachCurrentThread() != JNI_OK) 900 ALOGW("Warning: unable to detach main thread\n"); 901 if (mJavaVM->DestroyJavaVM() != 0) 902 ALOGW("Warning: VM did not shut down cleanly\n"); 903}
这里进入了不同的调用流程,Zygote和非Zygote模式,后面再分析
先看下startVm
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) 444{ ... 484 //获取vm的各种属性 485 property_get("dalvik.vm.execution-mode", propBuf, ""); 486 if (strcmp(propBuf, "int:portable") == 0) { 487 executionMode = kEMIntPortable; 488 } else if (strcmp(propBuf, "int:fast") == 0) { ... 768 /* 769 * Initialize the VM. 770 * 771 * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread. 772 * If this call succeeds, the VM is ready, and we can start issuing 773 * JNI calls. 774 */ 775 if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { 776 ALOGE("JNI_CreateJavaVM failed\n"); 777 goto bail; 778 } 779 780 result = 0; 781 782bail: 783 free(stackTraceFile); 784 return result; 785}
进入JNI_CreateJavaVM ,追踪得到是在libart.so里面
继续跟踪下一个startReg
1220/*static*/ int AndroidRuntime::startReg(JNIEnv* env) 1221{ 1222 /* 1223 * This hook causes all future threads created in this process to be 1224 * attached to the JavaVM. (This needs to go away in favor of JNI 1225 * Attach calls.) 1226 */ 1227 androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); 1228 1229 ALOGV("--- registering native functions ---\n"); 1230 1231 /* 1232 * Every "register" function calls one or more things that return 1233 * a local reference (e.g. FindClass). Because we haven't really 1234 * started the VM yet, they're all getting stored in the base frame 1235 * and never released. Use Push/Pop to manage the storage. 1236 */ 1237 env->PushLocalFrame(200); 1238 1239 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { 1240 env->PopLocalFrame(NULL); 1241 return -1; 1242 } 1243 env->PopLocalFrame(NULL); 1244 1245 //createJavaThread("fubar", quickTest, (void*) "hello"); 1246 1247 return 0; 1248}
进入register_jni_procs,可以看到是各种jni注册