Android本地服务的启动 - zygote服务及Dalvik环境启动

来源:互联网 发布:个性简历 知乎 编辑:程序博客网 时间:2024/06/05 16:35

通过上一节Android init进程启动的分析可知,init进程在启动过程中,解析并处理了init.rc和init.hardware.rc两个初始化脚本文件,在两个初始化脚本文件里,定义了一系列的service section,这些service在boot触发器下,通过class_start default依次启动,其过程总结如下:

    1. init 解析init.rc

    2. init 将init.rc里的service放到队列里面等待触发器的触发

    3. init通过 action_for_each_trigger("boot", action_add_queue_tail);触发boot Action

    4. 依次执行boot下的Commands,包括class_start default命令

    5. 所有的service默认的class为默认值:default,所以,所有init.rc中的service都被启动

zygote服务启动


通过init.rc中对zygote服务的描述可知,其对应的程序为:/system/bin/app_process

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media

该服务会在on boot时触发,其程序为/system/bin/app_process,服务名为zygote-Xzygote /system/bin --zygote --start-system-server为参数列表。

在创建了zygote 服务后,在目录下建立一个stream socket文件/dev/socket/zygote,权限为666,当zygote服务重启时,重启media服务

通过find ./ -name Android.mk  -exec grep -l app_process {} \; 命令,查找到,它在./frameworks/base/cmds/app_process/目录中被编译,其主要入口文件为:

./frameworks/base/cmds/app_process/app_main.cpp

找到该程序的main入口函数,

118 int main(int argc, const char* const argv[])
119 {
120     // These are global variables in ProcessState.cpp
121     mArgC = argc;
122     mArgV = argv;
123
124     mArgLen = 0;
125     for (int i=0; i<argc; i++) {
126         mArgLen += strlen(argv[i]) + 1;
127     }
128     mArgLen--;
129
130     AppRuntime runtime;
131     const char *arg;
132     const char *argv0;
133
134     argv0 = argv[0];
135
136     // Process command line arguments
137     // ignore argv[0]
138     argc--;
139     argv++;

141     // Everything up to '--' or first non '-' arg goes to the vm
142     // 在zygote服务的参数列表中,以‘--和非‘-’开头的参数,是dalvik的参数:/system/bin--zygote --start-system-server,交给Vm来处理

143     int i = runtime.addVmArguments(argc, argv);
144
145     // 找到zygote的目录:/system/bin
146     if (i < argc) {
147         runtime.mParentDir = argv[i++];
148     }
149
150     // 如果接下来的参数是:--zygote --start-system-server的话,设置argv0=“zygote”,startSystemServer= true,启动java VM
151     if (i < argc) {
152         arg = argv[i++];
153         if (0 == strcmp("--zygote", arg)) {
154             bool startSystemServer = (i < argc) ?
155                     strcmp(argv[i], "--start-system-server") == 0 : false;
156             setArgv0(argv0, "zygote");
157             set_process_name("zygote");
158             runtime.start("com.android.internal.os.ZygoteInit",
159                 startSystemServer);
160         } else {
161             set_process_name(argv0);
162
163             runtime.mClassName = arg;
164
165             // Remainder of args get passed to startup class main()
166             runtime.mArgC = argc-i;

167             runtime.mArgV = argv+i;
168
169             LOGV("App process is starting with pid=%d, class=%s.\n",
170                  getpid(), runtime.getClassName());
171             runtime.start();
172         }
173     } else {
174         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
175         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
176         app_usage();
177         return 10;
178     }
179
180 }

 根据service zygote的参数,启动VM:

runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);

runtime是AppRuntime的对象,AppRuntime是AndroidRuntime的子类:

runtime.start方法在AndroidRuntime里实现:

 859 void AndroidRuntime::start(const char* className, const bool startSystemServer)
 860 {
 861     LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");  // logcat里最显眼的字样
 862
 863     char* slashClassName = NULL;
 864     char* cp;
 865     JNIEnv* env;
 866
 867     blockSigpipe();
 868
 869     /*
 870      * 'startSystemServer == true' means runtime is obslete and not run from
 871      * init.rc anymore, so we print out the boot start event here.
 872      */
 873     if (startSystemServer) {
 874         /* track our progress through the boot sequence */
 875         const int LOG_BOOT_PROGRESS_START = 3000;
 876         LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
 877                        ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
 878     }

 880     const char* rootDir = getenv("ANDROID_ROOT");  // 取得Android的根目录:/system
 881     if (rootDir == NULL) {
 882         rootDir = "/system";
 883         if (!hasDir("/system")) {
 884             LOG_FATAL("No root directory specified, and /android does not exist.");
 885             goto bail;
 886         }
 887         setenv("ANDROID_ROOT", rootDir, 1);
 888     }
 889
 890     //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
 891     //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
 892
 893     /* start the virtual machine */

// 启动Dalvik虚拟机,在AndroidRuntime::startVm方法中,设备了大量VM的参数,最后调用JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs),通过JNI启动虚拟机
 894     if (startVm(&mJavaVM, &env) != 0)     

 895         goto bail;
 896
 897     /*
 898      * Register android functions.
 899      */
 900     if (startReg(env) < 0) {      // 注册系统使用的JNI函数
 901         LOGE("Unable to register all android natives\n");
 902         goto bail;
 903     }

 910     jclass stringClass;
 911     jobjectArray strArray;
 912     jstring classNameStr;
 913     jstring startSystemServerStr;
 914
 915     stringClass = env->FindClass("java/lang/String");          // 从Dalvik虚拟机里,查找到String类,
 916     assert(stringClass != NULL);
 917     strArray = env->NewObjectArray(2, stringClass, NULL);  // 创建一个String数组,有两个元素(strArray =  new String[2])
 918     assert(strArray != NULL);
 919     classNameStr = env->NewStringUTF(className);       // 创建一个Java String对象,初始值为:className,其实是start第一个参数:com.android.internal.os.ZygoteInit
 920     assert(classNameStr != NULL);
 921     env->SetObjectArrayElement(strArray, 0, classNameStr);   // 设置strArray 第一个元素的值为:classNameStr (strArray[0] =classNameStr)
 922     startSystemServerStr = env->NewStringUTF(startSystemServer ?
 923                                                  "true" : "false");   // 创建一个Java String对象,初始值为:startSystemServer ,其实是start第二个参数:true
 924     env->SetObjectArrayElement(strArray, 1, startSystemServerStr); // 设置strArray 第二个元素的值为:strArray[1] =startSystemServerStr

 925
 926     /*
 927      * Start VM.  This thread becomes the main thread of the VM, and will
 928      * not return until the VM exits.
 929      */

          // 根据上面的解释可知:准备启动Java VM,并且创建VM的主线程,只要VM不退出,这个主线程一直运行。
 930     jclass startClass;
 931     jmethodID startMeth;

 933     slashClassName = strdup(className);
 934     for (cp = slashClassName; *cp != '\0'; cp++)    // 将com.android.internal.os.ZygoteInit中的包分隔符‘.’换成‘/’即:com/android/internal/os/ZygoteInit
 
935         if (*cp == '.')
 936             *cp = '/';
 937
 938     startClass = env->FindClass(slashClassName);   // 从VM中查找ZygoteInit类,难道它要在VM里加载这个类。。。。
 939     if (startClass == NULL) {
 940         LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
 941         /* keep going */
 942     } else {
 943         startMeth = env->GetStaticMethodID(startClass, "main",
 944             "([Ljava/lang/String;)V");   // 查找到com/android/internal/os/ZygoteInit类中的main方法ID,接合Java文件命名规则,你能更深刻的理解,为什么主类名要和文件名一致,并且main方法为static方法。
 945         if (startMeth == NULL) {
 946             LOGE("JavaVM unable to find main() in '%s'\n", className);
 947             /* keep going */
 948         } else {
 949             env->CallStaticVoidMethod(startClass, startMeth, strArray);  // 调用ZygoteInit类里的main方法,这不是运行ZygoteInit这个JAVA程序吗!!
 950
 951 #if 0
 952             if (env->ExceptionCheck())
 953                 threadExitUncaughtException(env);
 954 #endif
 955         }
 956     }

 957
 958     LOGD("Shutting down VM\n");
 959     if (mJavaVM->DetachCurrentThread() != JNI_OK)
 960         LOGW("Warning: unable to detach main thread\n");
 961     if (mJavaVM->DestroyJavaVM() != 0)
 962         LOGW("Warning: VM did not shut down cleanly\n");
 963
 964 bail:
 965     free(slashClassName);
 966 }
 967
由上面的分析可知,
AndroidRuntime::start方法实现了下面功能:

  1> 通过startVm来启动虚拟机,并且注册了一些系统JNI函数,由于这个时候VM里还没有程序,只是个空的VM执行环境

  2> 通过AndroidRuntime::start的参数,在JNI代码里构建第一个Java程序ZygoteInit,将其作为VM的主线程,同时给其传递两个JNI构建的参数:

       "com/android/internal/os/ZygoteInit"和"true"

总结:

Android系统的启动是由init进程加载并启动了里面的/system/bin/app_process程序作为zygote服务,然后在zygote服务里执行runtime.start启动Dalvik虚拟机,加载了ZygoteInit类作为Dalvik虚拟机的第一个主线程。至此,Android的Java运行环境就准备完毕了。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 在闲鱼上买的电器是坏的怎么办 打开时全屏不知变成小屏怎么办 苹果6s原装数据线不充电怎么办 vivo手机安卓系统耗电快怎么办 电视机机顶盒插了电源开不了怎么办 苹果手机更新系统后老是闪退怎么办 16g苹果6s手机内存不足怎么办 苹果以前浏览器页面忽然没了怎么办 白衬衣被别的衣服染了怎么办 把宝贝标题改了没访客了怎么办 微信公众号看不到评论时间了怎么办 微店退款退货买家发空快递怎么办 微信二维码收款顾客少付款了怎么办 江西高考二本差5分上线怎么办 湖南文科考生二本上线差两分怎么办 在商场试鞋自己鞋子被偷怎么办 网易账号忘记密码更换手机了怎么办 一人在外地钱花光了怎么办 银行卡被公安冻结卡里的钱怎么办 在店铺不上班了押工资了怎么办? 在银座的押金拿不出来怎么办 唯品会退货时快递单号填错了怎么办 天猫店铺快递已发到不了怎么办 中邮消费贷没审核通过怎么办 房贷扣款日忘存钱了怎么办 农业银行卡输密码次数超限载怎么办 农业银行卡丢了不知道卡号怎么办 银行卡短信扣费失败怎么恢复怎么办 歌华有线遥控器点了tvav怎么办 一级注册结构延续注册晚了怎么办 在京东买的黄金项链买贵了怎么办 京东上面买的商品不符合实际怎么办 在京东买东西卖家迟迟不发货怎么办 淘宝商家买的货一直不到怎么办 国美买的格力空调发票丢了怎么办 国美实体店发票丢了怎么办 我在苏宁买的冰箱发票丢了怎么办 信用卡家庭电单位电话换了怎么办 常住户囗和实际住址没房子怎么办 退货淘宝极速退款 卖家拒收怎么办 淘宝退货极速退款后卖家拒收怎么办