Lua虚拟机初始化

转自:http://www.cnblogs.com/ringofthec/archive/2010/11/09/lua_State.htmlhtml

1. 建立lua虚拟机

lua_State *lua_newstate (lua_Alloc f, void *ud)编程

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

从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的内部组织结构, 下面是一张很归纳但能反映其结构的图lua

 

 

能够看出来, 在一个独立的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栈中.
相关文章
相关标签/搜索