加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

lua虚拟机初始化

发布时间:2020-12-14 22:08:00 所属栏目:大数据 来源:网络整理
导读:1. 创建lua虚拟机 lua_State *lua_newstate (lua_Alloc f,void *ud) 创建一个新的独立的lua虚拟机. 参数指定了内存分配策略及其参数,注意,让用户可以定制内存分配策略是十分有用的,比如在游戏服务器端使用lua,我做过一次统记lua在运行的时候会大量的分配大小

1. 创建lua虚拟机

lua_State *lua_newstate (lua_Alloc f,void *ud)

创建一个新的独立的lua虚拟机. 参数指定了内存分配策略及其参数,注意,让用户可以定制内存分配策略是十分有用的,比如在游戏服务器端使用lua,我做过一次统记lua在运行的时候会大量的分配大小小于128字节的内存块,在这样的环境下,使用lua原生的分配器就不太适合了,还好在服务器端,我们往往已经实现了memory pool,这时只需要写一个符合 lua_Alloc 原型的适配器,然后指定为lua的内存分配器就可以了,很灵活.

从lua的设计层面来说,lua只是内存分配器的用户,它只使用一个简单的接口来分配内存,而不去实现如何分配,毕竟内存分配不在lua的功能范围内,这样使的lua变的更加紧凑,它只是专注于实现lua本身,而不需要去关注内存分配策略这样的和lua本身无关的东西. 其实学习lua源代码不光是为了更好的掌握lua,也是为了学习lua中的体现出来的一些编程思想,lua是一个高度的一致性的,优雅的软件作品

失败返回null,多是因为内存分配失败了

该函数会创建栈

从该函数学习到的东西:? 1. 当你制作一个功能时,最好是理清该功能的核心概念和需求,然后去实现他们,功能要模块化,核心概念之间应该是概念一致的,联系紧密的[谈何容易,只能是尽可能的,随时提醒自己要有这样的想法].

??????????????????????????????? 2. 不要因为功能的实现问题而将一个非该功能核心概念的东西加进来,反之应该把这些东西抽象化作为用户可配置的形式.[在实现时很容易发生"要用到某个功能了,就是实现它"这样的情况,这样并不好]就比如lua,它的核心概念就是lua虚拟机,而内存分配只是在实现lua虚拟机的过程中的要用到的一种东西,但它本身不在lua的核心概念里面,所以把它暴露出来,让用户自己去定制.

??????????????????????????????? 再说下去就是:?除了系统最核心的功能,其他的东西能用插件的形式暴露给用户,使其可配置可扩展.

?

关于这个函数,还要做更多的解释,比如我们看到的lua的绝大多数api的第一个参数都是lua_State* L,而这个L就是lua_newstate制造出来的,那么在分析源码的时候,当然要去看看lua_newstate到底是干了些什么,lua_State的结构又是什么,要了解这些内容,需要知道lua的内部组织结构,下面是一张很概括但能反映其结构的图

JSZUY$VR25$M{O}OQV59XYW

可以看出来,在一个独立的lua虚拟机里,global_State是一个全局的结构,而lua_State可以有多个

值得说明的是,当调用lua_newstate的时候,主要的工作就是1. 创建和初始化global_State 2. 创建一个lua_State,下面来详细的讲解global_State的内容和作用.

?

global_State

一个lua虚拟机中只有一个,它管理着lua中全局唯一的信息,主要是以下功能

1. 内存分配策略及其参数,在调用lua_newstate的时候配置它们. 也可以通过lua_getallocf和lua_setallocf随时获取和修改它

2. 字符串的hashtable,lua中所有的字符串都会在该hashtable中注册.

3. gc相关的信息. 内存使用统计量.

4. panic,当无保护调用发生时,会调用该函数,默认是null,可以通过lua_atpanic配置.

5. 注册表,注册表是一个全局唯一的table.

6. 记录lua中元方法名称 和 基本类型的元表[注意,lua中table和userdata每个实例可以拥有自己的独特的元表--记录在table和userdata的mt字段,其他类型是每个类型共享一个元表--就是记录在这里].

7. upvalue链表.

8. 主lua_State,一个lua虚拟机中,可以有多个lua_State,lua_newstate会创建出一个lua_State,并邦定到global_state的主lua_State上.

global_State主要是管理lua虚拟机的全局环境.

lua_State

1. 要注意的是,和nil,string,table一样,lua_State也是lua中的一种基本类型,lua中的表示是TValue {value = lua_State,tt = LUA_TTHREAD}

2. lua_State的成员和功能

??? a. 栈的管理,包括管理整个栈和当前函数使用的栈的情况.

??? b. CallInfo的管理,包括管理整个CallInfo数组和当前函数的CallInfo.

??? c. hook相关的,包括hookmask,hookcount,hook函数等.

??? d. 全局表l_gt,注意这个变量的命名,很好的表现了它其实只是在本lua_State范围内是全局唯一的的,和注册表不同,注册表是lua虚拟机范围内是全局唯一的.

???? e. gc的一些管理和当前栈中upvalue的管理.

???? f. 错误处理的支持.

3. 从lua_State的成员可以看出来,lua_State最主要的功能就是函数调用以及和c的通信.

lua_State主要是管理一个lua虚拟机的执行环境,一个lua虚拟机可以有多个执行环境.

lua_newstate函数的流程

经过上面的分析,可以看出newstate = [new 一个 global_state] + [new 一个 lua_State],现在看一下它的流程,很简单

1. 新建一个global_state和一个lua_State.

2. 初始化,包括给g_s创建注册表,g_s中各个类型的元表的默认值全部置为0.

3. 给l_s创建全局表,预分配l_s的CallInfo和stack空间.

4. 其中涉及到了内存分配统统使用lua_newstate传进来的内存分配器分配.

?

2. 创建新lua执行环境

lua_State *luaE_newthread (lua_State *L)

创建一个新的lua_State,预分配CallInfo和stack空间,并共享l_gt表,虽然每个lua_State都有自己的l_gt,但是这里是却将新建的lua_State的l_gt都指向主lua_State的l_gt.

注意,lua_State是lua运行的基础[CallInfo]和与c通信的基础[stack],在新的lua_State上操作不会影响到原来的lua_State:),这个是协程实现的基础. 这里顺便提一下协程,这里先引一段lua创始人的话:" 我们不信任基于抢占式内存共享的多线程技术. 在 HOPL 论文中,我们写道: "我们仍然认为,如果在连 a=a+1 都没有确定结果的语言中,无人可以写出正确的程序." 我们可以通过去掉抢占式这一点,或是不共享内存,就可以回避这个问题."协程的基础就是"去掉抢占式,但共享内存",这里的共享是在lua虚拟机的层面上的,而不是通常意义上的share memory,这里的共享内存直接就指的是不同线程[lua_State]之间,共享lua_State.l_gt全局表,全局表可以作为不同协程之间的通信环境,当然也可以用lua_xmove函数,协程的事先说到这里.

一个和多lua_State相关的函数是: 在同一个lua虚拟机里传递不同lua_State的值

void lua_xmove (lua_State *from,lua_State *to,int n)
把from栈上的前n个值弹出,并压入到to栈中.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读