何为虚拟机

用于模拟计算机运行的程序.是个中间层,它处于脚本语言和硬件之间的一个程序.每一门脚本语言都会有自己定义的opcode(”操作码”),可以理解为这门程序自己定义的”汇编语言”.一般的编译型语言,比如C等,经过编译器编译之后生成的都是与当前硬件环境相匹配的汇编代码;而脚本型的语言,经过前端的处理之后,生成的就是opcode,再将该opcode放在这门语言的虚拟机中执行.虚拟机是作为单独的程序独立存在,而Lua由于是一门嵌入式的语言是附着在宿主环境中的.

lua代码到虚拟机执行的流程

在Lua中,Lua代码从词法分析到语法分析再到生成opcode,最后进入虚拟机执行的大体流程是什么样子的呢?

Lua的API中提供了luaL_dofile函数,它实际上是个宏,内部首先调用luaL_loadfile函数,加载Lua代码进行语法,词法分析,生成Lua虚拟机可执行的代码,再调用lua_pcall函数,执行其中的代码:

    #define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))

前半部分调用luaL_loadfile函数对Lua代码进行词法和语法分析,后半部分调用lua_pcall将第一步中分析的结果(也就是opcode)到虚拟机中执行.

首先来看luaL_loadfile函数,暂时不深入其中研究它如何分析一个Lua代码文件,先看它最后输出了什么.它最终会调用f_parser函数,这是对一个Lua代码进行分析的入口函数:

    static void f_parser (lua_State *L, void *ud) {
int i;
Proto *tf;
Closure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = luaZ_lookahead(p->z);
luaC_checkGC(L);
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
&p->buff, p->name);
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
cl->l.p = tf;
for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
cl->l.upvals[i] = luaF_newupval(L);
setclvalue(L, L->top, cl);
incr_top(L);
}

在完成词法分析之后,返回了Proto类型的指针tf,然后将其绑定在新创建的Closure指针上,初始化UpValue,最后压入Lua栈中.

不难想像,Lua词法分析之后产生的opcode等相关数据都在这个Proto类型的结构体中.

再来看lua_pcall函数是如何将产生的opcode放入虚拟机执行的.

lua_pcall函数中,首先获取需要调用的函数指针:

    c.func = L->top - (nargs+1);  /* function to be called */

这里的nargs是由函数参数传入的,luaL_dofile中调用lua_pcall时这里传入的参数是0,换句话说,这里得到的函数对象指针就是在f_parser函数中最后放入Lua栈的指针.

继续往下执行,走到luaD_call函数,有这一段代码:


if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
luaV_execute(L, 1); /* call it */

进入luaV_execute函数,这里是虚拟机执行代码的主函数:


void luaV_execute (lua_State *L, int nexeccalls) {
LClosure *cl;
StkId base;
TValue *k;
const Instruction *pc;
reentry: /* entry point */
lua_assert(isLua(L->ci));
pc = L->savedpc;
cl = &clvalue(L->ci->func)->l;
base = L->base;
k = cl->p->k;
/* main loop of interpreter */
for (;;) {
const Instruction i = *pc++;
StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
traceexec(L, pc);
if (L->status == LUA_YIELD) { /* did hook yield? */
L->savedpc = pc - 1;
return;
}
base = L->base;
}
/* warning!! several calls may realloc the stack and invalidate `ra' */
ra = RA(i);
// 以下是各种opcode的情况处理
}

可以看到,这里的pc指针里存放的是虚拟机opcode代码,它最开始从L->savepc初始化而来,而L->savepc在luaD_precall中赋值:

    L->savedpc = p->code;  /* starting point */

这里的p就是第一步f_parser中返回的Proto指针.

回顾一下整个流程:

  1. 函数f_parser中,对Lua代码文件的分析返回了Proto指针

  2. 函数luaD_precall中,将Lua_state的savepc指针指向1中的Proto结构体的code指针

  3. 函数luaV_execute中,pc指针指向2中的savepc指针,紧跟着就是一个大的循环体,依次取出其中的opcode进行执行.

lua虚拟机概述的更多相关文章

  1. 深入浅出Lua虚拟机

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文后面分享的Demo代码都是我一行一 ...

  2. 大佬带你深入浅出Lua虚拟机

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由鹅厂优文发表于云+社区专栏 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文 ...

  3. Lua虚拟机初始化

    转自:http://www.cnblogs.com/ringofthec/archive/2010/11/09/lua_State.html 1. 创建lua虚拟机 lua_State *lua_ne ...

  4. Lua虚拟机中的数据结构与栈

    Lua虚拟机中的数据结构与栈 来源 https://blog.csdn.net/zry112233/article/details/80828327 由上一篇文章可知解释器分析Lua文件之后生成Pro ...

  5. Azure 中的 Windows 虚拟机概述

    Azure 虚拟机 (VM) 是 Azure 提供的多种可缩放按需分配计算资源之一. 通常情况下,如果需要以更大的力度(相对于其他控制选项)控制计算环境,则应选择 VM. 本文介绍创建 VM 之前的注 ...

  6. java虚拟机概述

    java 虚拟机是什么?       java虚拟机是一个将字节码指令映射为对应物理操作系统指令的程序.       java程序的运行需要事先安装 jdk,而在jdk内部的jre中其核心就是 jvm ...

  7. Java 虚拟机概述

    虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬体架构,如处理器.堆栈.寄存器等,还具有相应的指令系统.Java虚拟机屏蔽了与具体操作系统平 ...

  8. 《Android虚拟机》----虚拟机概述

    No1: 虚拟机是指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离的环境中的完整计算机系统. No2: Java虚拟机由如下五个部分组成:一组指令集.一组寄存器.一个栈.一个无用单元收集堆. ...

  9. 【转】: 探索Lua5.2内部实现:虚拟机指令(1) 概述

    Lua一直把虚拟机执行代码的效率作为一个非常重要的设计目标.而采用什么样的指令系统的对于虚拟机的执行效率来说至关重要. Stack based vs Register based VM 根据指令获取操 ...

随机推荐

  1. apache ftp server的简单入门(java应用内嵌ftp server)

    Apache Ftp Server:(强调) Apache Ftp Server 是100%纯Java的FTP服务器软件,它采用MINA网络框架开发具有非常好的性能.Apache FtpServer ...

  2. ubuntu16.04安装网易云音乐

    源网址 对于网易,我只服云音乐,业界良心,用过的人都知道.我最喜欢的就是歌曲的评论功能,还有朋友圈子.里面有很多好段子,还有很多的好故事,基本上,不是分手,就是回忆初恋,还有吐槽的.我认为音乐带给人的 ...

  3. python modules and packages

    https://realpython.com/python-modules-packages/ 在软件开发中,一个module是具有一些相关功能的软件集合,比如,当你在开发一个游戏时,可能会有一个模块 ...

  4. memcpy 的内存拷贝函数

    #include <iostream> using namespace std; void *memory(void *dst,const void *src,size_t s) { co ...

  5. WeakValue & StoreValue

    WeakValue & StoreValue 源码 https://github.com/YouXianMing/WeakValue-StoreValue 说明 1. 这种设计并不是因为脑袋被 ...

  6. json格式转换(json,csjon)(天气预报)

    json格式数据默认为string,可以使用eval()函数或者json模块将其转换为dict.标准Json字符串必须使用双引号(")而不能使用单引号('),否则从字符串转换成dict类型会 ...

  7. Spring 读取配置文件的俩种方式

    读取配置可通过 org.springframework.core.env.Environment 类来获取, 也可以通过@Value的方式来获取 注解形式: @PropertySource({&quo ...

  8. 【linux】安装和配置 mysql服务器

    按照官网教程,根据自己的系统安装不同的发行版 https://dev.mysql.com/doc/refman/5.6/en/linux-installation-yum-repo.html 配置: ...

  9. Curator 基本API

    package bjsxt.curator.base; import java.util.List; import java.util.concurrent.ExecutorService; impo ...

  10. BZOJ1022:[SHOI2008]小约翰的游戏John(博弈论)

    Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...