Android模拟器源码Qemu Study for Android Emulator

news/2025/4/1 7:32:48/

这两天看了下android emulator的源代码,位置在android-src/external/qemu里面,

编译和启动的方式很简单;

$ ./android-configure.sh
$ make
$ export ANDROID_SDK_ROOT=/path/to/androdi-sdk
$ emulator-arm @4.2

你可以对源码进行修改,然后重新编译、使用,而这里主要要讲的是qemu的运行原理,

资料来源是 Qemu detailed study。要说明的一点是,android emulator原理基本上是和qemu一样的,只是加了一些android specific的东西在里面。

首先是qemu整体流程:

qemu process

首先将guest code(这里即为arm code)被TCG(Tiny Code Generator)转换成一个中间表达,然后再转换成host code(这里即为x86 code),具体来说分为两步:

  • 一个TB(Translation Block)被翻译成TCG ops
  • TCG ops被翻译成host code

我们先来看下qemu的code base:

qemu code base

  • vl.c/vl-android.c: 这个是整个qemu的入口函数,主要是初始化qemu环境,然后进入main_loop
  • target-xyz/translate.c: 将guest code翻译成TCG ops;
  • tcg/*/tcg-target.c: 将TCG ops翻译成host code;
  • tcg/tcg.c: TCG的主函数;
  • cpu-exec.c: 寻找下一个TB(如果没找到则调用tcg.c生成TB),然后执行。

在qemu中也很好地利用了locality,即没产生一段code(TCG ops或host code),就将其存在一个code cache中,然后用LRU进行替换。

运行流程(code perspective)

主要分为两部分: 代码生成代码运行

代码生成

这是主要部分,流程是这样的:

qemu process from code perspective

其中函数cpu_exec()相当于主要的执行循环函数,它将TB第一次初始化,在两个嵌套无限for循环中通过tb_find_fast()来获得host code TB,然后通过tcg_qemu_tb_exec()来执行相应代码。

tb_find_fast会首先查看code cache中是否有TB存在了,有则直接执行tcg_qemu_tb_exec(),否则通过tb_find_slow()来查找或者生成TB,后者通过一系列调用,最后到达disas_insn(),该函数执行了实际的guest code到TCG ops的翻译,并将其加入TCG ops的code buffer,最后调用tcg_gen_code()来生成host code。

代码运行

代码运行就是通过tcg_qem_tb_exec()来实现的,可以看到,其实这是一个宏,定义在tcg/tcg.h里面:

#define tcg_qemu_tb_exec(tb_ptr) \((long REGPARM __attribute__ ((longcall)) (*)(void *))code_gen_prologue)(tb_ptr)

这是一个感觉非常复杂的调用,我们知道, ((long REGPARM (*)(void *)) 是一个指向函数的指针,void *是它的参数,返回值为long;而在这里REGPARAM(*)是一个GCC选项,表示函数是通过寄存器传参而不是通过栈传参的。

而一个数组的名字表示的是指向这个数组的基地址,于是,(function_pointer) array_name则会将这个基地址cast成一个函数地址。

另外,一个函数可以通过(*pointer_to_func)(args)被调用,所以((long REGPARM (*)(void *))code_gen_prologue)(tc_ptr)进行了一次函数调用,似乎在这里少了一个*号,不过其实只要测试下可以发现(*pointer_to_func)(args)(pointer_to_func)(args)是一样的。

所以上面tcg_qemu_tb_exec(tb_ptr)翻译的宏可以表示为一个数组code_gen_prologue被cast成一个函数指针,参数为tc_ptr,返回值为long(指向下一个TB),并且被调用。其实,被code_gen_prologue指向的函数就是Function Prologue,将控制流转到tc_ptr指向的host code开头部分。




http://www.ppmy.cn/news/617408.html

相关文章

一个完整的NES模拟器

(这个版本的忍者神龟,好多年都没玩过了。译者) 也许不久后,你就可以在android手机上重温以前在电视上玩塞尔达和超级玛丽来度过暑假的日子了,就是这个NES模拟器。 模拟器有两个版本:lite版,你只能玩一个指定的游戏(也就…

Android模拟器怎么root

首先,参考这两篇文章,我这里是作补充说明 https://www.jianshu.com/p/fd39ec466e88 https://blog.csdn.net/ocean20/article/details/82798004 1.启动模拟器 emulator -list-avds查看avd列表 emulator -avd Nexus_5X_API_26 -writable-system启动avd …

01 QEMU仿真器-模拟器介绍

QEMU仿真器-模拟器介绍 作者将狼才鲸创建日期2022-05-28 所属的Gitee源码和工程地址:才鲸嵌入式 / 开源安防摄像机(嵌入式软件) 一、QEMU模拟器(仿真器)介绍 如果你也像我一样,虽然学过电子和硬件&#…

Android 5 Emulator root 模拟器 root

前言: 网上google很久一直找不到root android 5.0 emulator答案,要么是真机的root居多,要么android版本4.0的,要么是su 和 相关的superapk不是最新的。要么 是参考人家的命令步骤就特么不成功,要么按照人家命令弄重启…

安卓模拟器手动root

转载自:http://quantoubao.blog.163.com/blog/static/2083211702013870501987/ 安装Android SDK安卓模拟器的方法很简单,网上大把,傻瓜式的。不过对其root的方法,网上的版本就不那么好使了。网上的方法从方向性来说是没错的&…

Android模拟器Root

Android模拟器Root 前言需要的准备的资料操作步骤一、进入Android SDK的安装目录二、以可写方式启动模拟器三、安装Supersu.apk四、向系统添加su文件五、修改su文件权限六、安装su二进制文件,设置后台守护程序七、设置SELinux的限制八、安装Root Explorer 写在最后 …

使用Android 模拟器运行自定义Rom

运行编译过的android源码最简单的方式是在编译完成后直接执行emulator。 但是,一般情况下我们都在服务器编译源码,或者在另外一台机器上编译出来 iso文件。 这种情况我们需要手动设置一下avd 使其能够在虚拟机上运行。具体步骤如下(以windows…

自定义android模拟器,在模拟器上运行自定义Android ROM

我建立了一个基于AOSP的自定义ROM(Nexus 6的7.0),我想将这个ROM与SDK模拟器一起使用.我相信这个版本的午餐组合是’aosp_x86_64-eng’ 应该适用于SDK模拟器.但是,我在AVD Manager中看不到指定我的自定义系统映像的选项.它只允许我使用谷歌列出的ROM. 我尝试将我的自定义ROM的sy…