位置: 编程技术 - 正文

Android系统启动过程全解析(Android系统启动负载均衡)

发布时间:2024-02-27

推荐整理分享Android系统启动过程全解析(Android系统启动负载均衡),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:android系统启动优化,android系统启动过程,android系统启动优化,Android系统启动流程,android系统启动应用后内存不增加,Android系统启动流程,android系统启动应用后内存不增加,android系统启动过程,内容如对您有帮助,希望把文章链接给更多的朋友!

原文地址: 从内核之上,我们首先应该从文件系统的init开始,因为 init 是内核进入文件系统后第一个运行的程序,通常我们可以在linux的命令行中指定内核第一个调用谁,如果没指定那么内核将会到/sbin/、/bin/ 等目录下查找默认的init,如果没有找到那么就报告出错。

init.c位置:system/core/init/init.c。

在init.c的main函数里面完成以下步骤:

1、创建设备节点。

2、初始化log系统。

3、解析init.rc文件,解析函数在同一目录的parser.c里面实现。

4、初始化属性服务器,在同一目录下的property_service.c里面实现。

。。。。

最后、进入loop等待事件到来。

init.rc的解析过程

init.rc是一个初始化脚本,路径(不确定):device/renesas/emev/init.rc

在init.c的main函数里面,调用parser.c的parse_config_file("/init.rc");执行解析过程。

先读取文件内容到data里面,再调用parse_config(fn, data);进行解析。

init.rc包含Android初始化语言的四大类声明:行为类(Actions)、命令类(Commands)、服务类(Services)、选项类(Options),解析完会形成两个列表service_list 和action_list。

其中有一个很重要的服务就是zygote,在init.rc里面的片段:

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

这是脚本中service的&#;式:

Java代码service <name> <pathname> [ <argument> ]* <option> <option> ...

zygote对应的可执行文件为app_process,android2.2中它的源代码位置:framework/base/cmds/app_process。

app_main.cpp的main函数,它先调用AndroidRuntime::addVmArguments将它的参数“-Xzygote /system/bin”传给AndroidRuntime作为启动JavaVM用。接着如果定位余下的参数,如果有"--zygote",执行下面代码,从参数可以知道,这时候要求启动start system server,并且将com.android.internal.os.ZygoteInit装载至虚拟机。

C&#;&#;代码ZygoteInit.java的main方法)。 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); }

否则不启动system server:

C&#;&#;代码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();

runtime是AppRuntime对象,继承自AndroidRuntime,在AndroitRuntime.app里的start()函数如下,默认装载的是RuntimeInit进程,不启动system server。

C&#;&#;代码void AndroidRuntime::start() { start("com.android.internal.os.RuntimeInit", false /* Don't start the system server */); } Android系统启动过程全解析(Android系统启动负载均衡)

在AndroidRuntime.cpp的start方法内,先启动JAVA虚拟机,在定位执行className类的main方法(如果才存在的话)。

C&#;&#;代码void AndroidRuntime::start(const char* className, const bool startSystemServer) { LOGD("n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<n"); /* start the virtual machine */ if (startVm(&mJavaVM, &env) != 0) goto bail; startClass = env->FindClass(slashClassName); if (startClass == NULL) { LOGE("JavaVM unable to locate class '%s'n", slashClassName); /* keep going */ } else { startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { LOGE("JavaVM unable to find main() in '%s'n", className); /* keep going */ } else { env->CallStaticVoidMethod(startClass, startMeth, strArray); } } }

先看怎么启动虚拟机的,在startVm方法内,先将一些系统参数选项,包括虚拟机相关的属性,保存到一个JavaVMOption的实例内,比如虚拟机的堆大小,是否check jni,JNI版本信息,最后将这些参数传给JNI_CreateJavaVM,创建JAVA虚拟机实例。

C&#;&#;代码//JNI_CreateJavaVM在jni.h中有声明,代码位置:dalvik/libnativehelper/include/nativehelper/,在Jni.c中有定义 jint JNI_GetDefaultJavaVMInitArgs(void*); jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*); jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);

在JNI_CreateJavaVM中,先检查JNI的版本,为JavaVM,JNIEnv开辟空间,保存通用接口,最后解析传进来的参数,最后调用dvmStartup启动虚拟机(有些传给JNI_CreateJavaVM的参数,也直接传给了dvmStartup)。

这里的JNIEnv实际是JNIEnvExt强制转换过来的,JNIEnvExt是JNIEnv结构体的扩展,JNIEnExt前端与JNIEnv完全对齐,都是JNI函数指针。相当于JNIEnExt对JNIEnv进行了赋&#;。

C&#;&#;代码pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);

在dvmStartup在Init.c定义,先调用setCommandLineDefaults进行一些默认的设置,比如虚拟机的默认heap大小。

C&#;&#;代码static void setCommandLineDefaults() { gDvm.heapSizeStart = 2 * * ; // Spec says MB; too big for us. gDvm.heapSizeMax = * * ; // Spec says % physical mem gDvm.stackSize = kDefaultStackSize; }

然后调用dvmProcessOptions处理传进来的参数,比如是否执行zygote,最后,根据gDvm.zygote的&#;,是否申请一个新的堆,这个&#;在有参数-Xzygote置1。

C&#;&#;代码if (gDvm.zygote) { if (!dvmInitZygote()) goto fail; } else { if (!dvmInitAfterZygote()) goto fail; }

到这里,虚拟机算是启动成功了。

回到AndroidRuntime.cpp的start方法,现在我们要启动ZygoteInit进程,找到ZygoteInit的main方法,调用env->CallStaticVoidMethod(startClass, startMeth, strArray);去启动它。

CallStaticVoidMethod在Jni.c里面有定义,但不是直接定义的,因此用CallStaticVoidMethod作为函数名直接查定义是查不到的,是这样定义的:

CALL_STATIC(void, Void, , , false);

再看CALL_STATIC的宏定义:

C&#;&#;代码#define CALL_STATIC(_ctype, _jname, _retfail, _retok, _isref) static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass jclazz, jmethodID methodID, ...) { UNUSED_PARAMETER(jclazz); JNI_ENTER(); JValue result; va_list args; va_start(args, methodID); dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args); va_end(args); if (_isref && !dvmCheckException(_self)) result.l = addLocalReference(env, result.l); JNI_EXIT(); return _retok; } static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass jclazz, jmethodID methodID, va_list args) { UNUSED_PARAMETER(jclazz); JNI_ENTER(); JValue result; dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args); if (_isref && !dvmCheckException(_self)) result.l = addLocalReference(env, result.l); JNI_EXIT(); return _retok; } static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass jclazz, jmethodID methodID, jvalue* args) { UNUSED_PARAMETER(jclazz); JNI_ENTER(); JValue result; dvmCallMethodA(_self, (Method*)methodID, NULL, true, &result, args); if (_isref && !dvmCheckException(_self)) result.l = addLocalReference(env, result.l); JNI_EXIT(); return _retok; }

因此CallStaticVoidMethod调用的是dvmCallMethodV方法,至于怎么样再调用到ZygoteInit的main方法,有待研究,现在直接看ZygoteInit的main方法,它的参数是这样定义的:

C&#;&#;代码stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(2, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false"); env->SetObjectArrayElement(strArray, 1, startSystemServerStr);

申请一个String变量,给把类名作为第0个参数,第二个参数是"ture"或"false",用来决定是否启动system service,在ZygoteInit的main方法会读取这个参数。

C&#;&#;代码if (argv[1].equals("true")) { startSystemServer(); } else if (!argv[1].equals("false")) { throw new RuntimeException(argv[0] &#; USAGE_STRING); }

它读取到第一个参数是"true",所以调用startSystemServer启动system server,在startSystemServer中,调用Zygote的forkSystemServer,fork出来的子进程,就是system server了,调用事的参数如下:

C&#;&#;代码String args[] = { "--setuid=", "--setgid=", "--setgroups=,,,,,,,,,,,,", "--capabilities=,", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", };

这些参数解析到一个ZygoteConnection.Arguments对象中。forkSystemServer方法实际上是JNI方法,在vm/native/dalvik_system_Zygote.c中有定义。

C&#;&#;代码static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult) { pid_t pid; pid = forkAndSpecializeCommon(args); if (pid > 0) { int status; LOGI("System server process %d has been created", pid); gDvm.systemServerPid = pid; if (waitpid(pid, &status, WNOHANG) == pid) { LOGE("System server process %d has died. Restarting Zygote!", pid); kill(getpid(), SIGKILL); } } RETURN_INT(pid); }

具体的fork操作在forkAndSpecializeCommon里面进行,父进程检查子进程是否died。

在forkAndSpecializeCommon,先判断是否zygote模式,是否剩余有足够的heap空间,最后才执行fork()系统调用。

fork之后,父进程不做操作,子进程调用dvmInitAfterZygote去为自己申请堆空间。

子进程返回到startSystemServer方法。

C&#;&#;代码/* For child process */ if (pid == 0) { handleSystemServerProcess(parsedArgs); }

调用handleSystemServerProcess方法,在里面先设置uid的权限,再调用RuntimeInit.zygoteInit。

C&#;&#;代码/* * Pass the remaining arguments to SystemServer. * "--nice-name=system_server com.android.server.SystemServer" */ RuntimeInit.zygoteInit(parsedArgs.remainingArgs); /* should never reach here */

在zygoteInit里面调用invokeStaticMain,invokeStaticMain先将com.android.server.Systemserver类的main方法取出,作为Method对象,然后和参数一起传给ZygoteInit.MethodAndArgsCaller,MethodAndArgsCaller继承自Runner,最终MethodAndArgsCaller调用Method.invode函数启动System Server。

Android源代码分析要看这本书 原文地址:

Android XML布局详解 - XML Layouts AndroidXML布局详解-XMLLayoutsXML布局作为用户界面直接作用显示在Activity(活动、界面)上。它定义了布局结构,并把所有在布局里的元素显示给用户,可以在

android NDk初步学习以及某些小问题的解决方法备忘 二 转载地址:

标签: Android系统启动负载均衡

本文链接地址:https://www.jiuchutong.com/biancheng/385124.html 转载请保留说明!

上一篇:下拉列表框Spinner的使用(下拉列表框模糊匹配)

下一篇:Android源代码分析要看这18本书(安卓源代码开放吗)

  • 购买土地缴纳的费用
  • 工程结算属于什么行业
  • 小企业一定要买五险吗
  • 开增值税发票规格是否可以不用填
  • 专用发票超过360天认证期怎么办?
  • 已经验旧的发票可以作废吗
  • 哪些税金不得在借方增加
  • 出售无形资产计入资产处置损益还是营业外收入
  • 税控系统技术维护费抵税怎么申报
  • 承包工程会计账务处理流程
  • 业务招待费比例扣除额
  • 公司用现金发放工资在税法上合规吗
  • 进项发票不够如何避税
  • 电信报表系统
  • 金融保险法
  • 代订住宿费可以开专票吗
  • 工程发票预交税金规定
  • 交通费,通讯费均按照上级行标准领取
  • 个体户经营所得核定税率
  • 方正电脑u盘启动按什么键
  • 出口货物退税率为0,是否出口免税
  • windows11怎么设置锁屏时间
  • 企业并购特殊性税务处理
  • 会计分录的书写规范
  • 偷税漏税的会计要负什么责任
  • encore是什么软件
  • 异构图神经网络 电影推荐
  • PHP:mcrypt_enc_is_block_algorithm()的用法_Mcrypt函数
  • 直接计入所有者权益的交易或事项
  • 国家规定发票多久之内可以开
  • 获取vue实例
  • 冬日里的科赫尔湖,德国巴伐利亚州 (© Reinhard Schmid/eStock Photo)
  • Yii使用migrate命令执行sql语句的方法
  • 工程完工后的质量抽检不合格怎么办
  • rmt命令 远端磁带传输协议模块
  • php sha1加密 解密
  • ajax调用php接口
  • 溢价购买子公司账务处理
  • bash详解
  • 外地预交的企业所得税如何在季度企业所得税申报
  • 科技型中小企业查询
  • ca证书收费金额是多少?
  • 客户的赔偿金会计分录
  • mysqlbinlog -vvv
  • 出口退税抵减应纳税额
  • 金蝶系统结账之后反结账
  • 应交税费增值税销项税
  • 材料成本差异的超支与节约
  • 企业发生的职工福利费支出,不超过工资
  • 增值税专用发票的税率是多少啊
  • 已认证进项税转出口退税怎么处理
  • 房地产结转收入的条件
  • 简易计税项目的进项税能抵一般项目的销项税额吗?
  • 期间费用明细表必须填吗
  • 结转清理净损失怎么算
  • 技术服务收入如何纳税
  • 月底计提工资的会计处理
  • SQL Server ltrim(rtrim()) 去不掉空格的原因分析
  • sql server使用教程
  • mysql中union用法
  • mysql m1
  • xp系统打开软件慢怎么解决
  • 不同的linux系统命令一样吗
  • linux服务器安装虚拟机
  • 微软推送win10更新 蓝牙
  • win7和linux双系统
  • route.exe - route是什么进程 有什么用
  • 如何关闭windows密钥
  • win10如何恢复已删除的密钥
  • pascl32.exe - pascl32是什么进程 有什么用
  • 如何永久激活win11
  • [置顶]JM259194
  • ie6怎么设置兼容性
  • 你知道python不
  • js函数function用法
  • unity怎么替换模型位置
  • jquery实现ajax提交表单信息的简单方法(推荐)
  • android开发模式
  • 农产品销售个人所得税
  • 乾升黄酒好吗值得买吗
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号