IT培训机构|91免费精品视频|专注编程培训|91免费精品|软件开发培训_91免费国产视频_华清远见教育

當前位置: > 華清遠見教育科技集團 > 嵌入式學習 > 講師博文 > Android本地服務的啟動
Android本地服務的啟動
時間:2016-12-12作者:華清遠見

通過上一節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入口函數,

int main(int argc, const char* const argv[])
    {
        // These are global variables in ProcessState.cpp
        mArgC = argc;
        mArgV = argv;
        mArgLen = 0;
        for (int i=0; i< argc; i++) {
            mArgLen += strlen(argv[i]) + 1;
            }
        mArgLen--;
        AppRuntime runtime;
        const char *arg;
        const char *argv0;
        argv0 = argv[0];
        // Process command line arguments
        // ignore argv[0]
        argc--;
        argv++;
        // Everything up to '--' or first non '-' arg goes to the vm
        // 在zygote服務的參數列表中,以'--和非'-'開頭的參數,是dalvik的參數:/system/bin--zygote --start-system-server,交給Vm來處理
        int i = runtime.addVmArguments(argc, argv);
        // 找到zygote的目錄:/system/bin
        if (i < argc) {
            runtime.mParentDir = argv[i++];
        }
        // 如果接下來的參數是:--zygote --start-system-server的話,設置argv0="zygote",startSystemServer= true,啟動java VM
        if (i < argc) {
            arg = argv[i++];
            if (0 == strcmp("--zygote", arg)) {
                bool startSystemServer = (i < argc) ?
                strcmp(argv[i], "--start-system-server") == 0 : false;
                setArgv0(argv0, "zygote");
                set_process_name("zygote");
                runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer);
        } else {
            set_process_name(argv0);
            runtime.mClassName = arg;
            // Remainder of args get passed to startup class main()
            runtime.mArgC = argc-i;
            runtime.mArgV = argv+i;
            LOGV("App process is starting with pid=%d, class=%s.\n",
            getpid(), runtime.getClassName());
            runtime.start();
            }
        } else {
                LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
                fprintf(stderr, "Error: no class name or --zygote supplied.\n");
                app_usage();
                return 10;
        &nbnbsp;   }
    }

根據service zygote的參數,啟動VM:

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

runtime是AppRuntime的對象,AppRuntime是AndroidRuntime的子類:

runtime.start方法在AndroidRuntime里實現:

void AndroidRuntime::start(const char* className, const bool startSystemServer)
    {
        LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");        //logcat里顯眼的字樣
        char* slashClassName = NULL;
        char* cp;
        JNIEnv* env;
        blockSigpipe();
        /*
        * 'startSystemServer == true' means runtime is obslete and not run from
        * init.rc anymore, so we print out the boot start event here.
        */
        if (startSystemServer) {
        /* track our progress through the boot sequence */
        const int LOG_BOOT_PROGRESS_START = 3000;
        LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
        ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
        }
        const char* rootDir = getenv("ANDROID_ROOT"); // 取得Android的根目錄:/system
        if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
        LOG_FATAL("No root directory specified, and /android does not exist.");
        goto bail;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
        }
        //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
        //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
        /* start the virtual machine */
        // 啟動Dalvik虛擬機,在AndroidRuntime::startVm方法中,設備了大量VM的參數,后調用JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs),通過JNI啟動虛擬機
        if (startVm(&mJavaVM, &env) != 0)
        goto bail;
        /*
        * Register android functions.
        */
        if (startReg(env) < 0) { // 注冊系統使用的JNI函數
        LOGE("Unable to register all android natives\n");
        goto bail;
        }         jclass stringClass;
        jobjectArray strArray;
        jstring classNameStr;
        jstring startSystemServerStr;
        stringClass = env->FindClass("java/lang/String");        // 從Dalvik虛擬機里,查找到String類,
        assert(stringClass != NULL);         strArray = env->NewObjectArray(2, stringClass, NULL);        // 創建一個String數組,有兩個元素(strArray = new String[2])
        assert(strArray != NULL);
        classNameStr = env->NewStringUTF(className);        // 創建一個Java String對象,初始值為:className,其實是start第一個參數:com.android.internal.os.ZygoteInit
        assert(classNameStr != NULL);
        env->SetObjectArrayElement(strArray, 0, classNameStr);        // 設置strArray 第一個元素的值為:classNameStr (strArray[0] =classNameStr)
        startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");        // 創建一個Java String對象,初始值為:startSystemServer ,其實是start第二個參數:true
        env->SetObjectArrayElement(strArray, 1, startSystemServerStr);        // 設置strArray 第二個元素的值為:strArray[1] =startSystemServerStr
        /*
        * Start VM. This thread becomes the main thread of the VM, and will
        * not return until the VM exits.
        */
        // 根據上面的解釋可知:準備啟動Java VM,并且創建VM的主線程,只要VM不退出,這個主線程一直運行。
        jclass startClass;
        jmethodID startMeth;
        for (cp = slashClassName; *cp != '\0'; cp++)        //
將com.android.internal.os.ZygoteInit中的包分隔符'.'換成'/'即:com/android/internal/os/ZygoteInit
        if (*cp == '.')
        *cp = '/';
        startClass = env->FindClass(slashClassName);         // 從VM中查找ZygoteInit類,難道它要在VM里加載這個類。。。。
        if (startClass == NULL) {
        LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
        } else {
        startMeth = env->GetStaticMethodID(startClass, "main",
        "([Ljava/lang/String;)V"); //
        查找到com/android/internal/os/ZygoteInit類中的main方法ID,接合Java文件命名規則,你能更深刻的理解,為什么主類名要和文件名一致,并且main方法為static方法。
        if (startMeth == NULL) {
        LOGE("JavaVM unable to find main() in '%s'\n", className);
        /* keep going */
        } else {
        env->CallStaticVoidMethod(startClass, startMeth, strArray);        // 調用ZygoteInit類里的main方法,這不是運行ZygoteInit這個JAVA程序嗎!!
        #if 0
        if (env->ExceptionCheck())
        threadExitUncaughtException(env);
        #endif
            }
        }
        LOGD("Shutting down VM\n");
        if (mJavaVM->DetachCurrentThread() != JNI_OK)
        LOGW("Warning: unable to detach main thread\n");
        if (mJavaVM->DestroyJavaVM() != 0)
        LOGW("Warning: VM did not shut down cleanly\n");
        bail:
        free(slashClassName);
    }

由上面的分析可知,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運行環境就準備完畢了。

發表評論
評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
主站蜘蛛池模板: 三禾防爆-专业的防爆电气生产厂家 | 临沂人才网_临沂招聘网_【官方网站】| 金相切割机-金相磨抛机-显微/维氏/布氏/洛氏硬度计-自准直仪-金相显微镜-万能材料试验机-清洁度检测仪-淋雨试验机-上海中研精密仪器制造有限公司 | 中科盛世酒窖 - 酒窖设计_酒窖工程_酒窖空调设备_恒温酒柜定制_私人别墅家庭酒窖_不锈钢红酒柜_实木雪茄柜 | 长沙思辰仪器科技有限公司| 矿用精确定位系统,井下4G无线通讯系统,工作面集控系统,皮带保护系统-山东新云鹏电气有限公司 | 衡水一体化污水处理设备|循环水旁滤器|加药装置|钢厂浊环净化装置|河北欧意科技集团有限公司 | 无土栽培|无土栽培技术|水肥一体化|无土栽培蔬菜 | 消泡剂厂家-水处理消泡剂-有机硅消泡剂-广东广州多美多消泡剂厂家 | 专业提供医疗器械,医疗设备,进口国产医疗设备,医疗耗材采购,医疗设备厂家等医疗器械信息-上海聚慕医疗器械有限公司 | 义乌供需网-义乌外发加工来料加工,义乌采购信息供求对接平台(yiwugongxu.com) | 西安测试仪-西安电压测试仪-西安电流测试仪-西安热油汽水测试仪-西安阻抗测试仪-西安时间速度测试仪-西安电力设备厂家-西安中洲电力设备有限公司 | 烟台通风管道,烟台风机风管,烟台风阀-烟台福莱通风设备有限公司 烟台天昊矿业有限公司、滑石、滑石粉、微细粉、滑石矿-烟台天昊矿业有限公司 | 健力普医疗-半导体激光治疗仪,红外偏振光治疗仪,近红外线治疗仪-独家功能,光疗典范 | 无锡今飞激光技术有限公司-手持激光焊接机_激光打标机_激光清洗机_平台激光焊接机_焊接专机- | 小字符喷码机,激光喷码机,喷码机厂家_山东闪创电子设备有限公司 小型生活污水处理设备_MBR膜生物反应器_口腔医院/脱脂污水处理设备_酸洗磷化/喷涂废水处理设备-上海台江环保 | 上海离婚律师|婚姻律师离婚纠纷咨询解答-金牌上海离婚律师团队 | 硫化剂|双马树脂|交联剂-宿迁志晟科技有限公司 | 益家304不锈钢水管厂家|批发代理|价格|薄壁|广东益家管业有限公司 | 转盘萃取塔,DMF回收塔生产厂家-无锡弘鼎华化工设备有限公司 | 厌氧培养系统_厌氧工作站_厌氧培养装置_智能厌氧培养_常州普莱实验系统 | 上海上市答谢酒会_企业年会_新品上市发布会_周年/开业庆典_会议会务_活动策划布置演出公司 | 金华银焊条-金华银焊丝-银焊片制造商-银焊环批发商-浙江焊丝生产商-焊环厂家-浙江永旺焊材制造有限公司 | 活性氧化铝球-活性氧化铝干燥剂厂家价格-3A-5A分子筛-巩义市亿洋水处理材料有限公司 | 陶瓷靶材_氧化铌靶材_合金靶材_专注河北氧化铌靶材批发-河北东同光电科技有限公司 | 郑州环球重工机械有限公司建筑垃圾处理专题网站 | 正规网上赚钱网站「百赚网」专注在家赚钱的网络赚钱平台 | 陕西筱润智能科技有限公司 干部人事智能档案柜 智能密集架 智能档案柜 部队选层文件智能柜 智能枪弹柜 财务智能档案柜 边防武警智能密集架 医院智能档案柜 部队选层文件智能柜智能枪弹柜 学校医院文件柜 企事业单位公检法智能文件柜 生产厂家-筱润智能科技有限公司 RFID射频智能密集架 全自动智能选层档案柜 智能密保柜 枪柜部队营房营具床桌椅办公家具 办公用品档案盒设备货架 全自动智能选层柜生产厂家-筱润智能科技有限公司 | 猪粪烘干机|小型鸡粪烘干机|猪粪烘干机价格|小型鸡粪烘干机价格 - 河南宏科重工干燥机设备生产厂家 | 蒸汽孔板流量计-法兰式孔板流量计-一体化标准孔板流量计-金湖中原仪表有限公司 | 景德镇晶达新材料有限公司| 纸箱抗压测定仪|电脑测控耐破度仪|电脑抗张试验仪|杭州华翰仪器百科 | 输送机|滚筒输送机|皮带输送机|滚筒|无动力滚筒|万向球生产厂家-上海霞韵输送机械设备有限公司 | 医用手摇病床,医用电动病床,康养手摇病床,康养电动病床-河北丁丁医疗器械有限公司 | 抛丸机-通过式抛丸机-履带吊钩式抛丸机厂家-青岛泓霖智能设备公司 | 亿企商贸-亿万企业的商务贸易平台-B2B企业产品发布供求信息平台,一带一路中国企业及产品展示平台,免费企业智能自助建站网络营销推广平台,打造B2B企业黄页产品信息发布推广专业综合电子商务平台! | 生物柴油_油酸甲酯厂家_脂肪酸甲酯_植物油燃料-中凯化工 | 极限软件园-绿色免费软件下载站 吉林市康艺商贸有限公司_吉林市康艺商贸有限公司 | 疲劳试验机|电子万能试验机|摩擦磨损试验机|冲击试验机|济南全力测试技术有限公司 | 联智通达_工控一体机_工业触摸一体机_工业一体机_工业触控一体机_POS机主板_工控主板_国产化主板_RK3588主板厂商-联智通达 | 山东金起起重机械有限公司[官网]-金桥银路悬臂吊,金起龙门吊,山东金起起重行吊,单梁起重机 |