android中的本地服务,Android本地服务的启动

通过上一节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的子类:

a46cd5736bef2ea76a0fca1ba48f684c.png

runtime.start方法在AndroidRuntime里实现:

void AndroidRuntime::start(const char* className, const bool startSystemServer)

{

LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<

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运行环境就准备完毕了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值