Lua虚拟机初始化
转自:http://www.cnblogs.com/ringofthec/archive/2010/11/09/lua_State.html
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的内部组织结构, 下面是一张很概括但能反映其结构的图
可以看出来, 在一个独立的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栈中.
Lua虚拟机初始化的更多相关文章
- lua虚拟机概述
何为虚拟机 用于模拟计算机运行的程序.是个中间层,它处于脚本语言和硬件之间的一个程序.每一门脚本语言都会有自己定义的opcode("操作码"),可以理解为这门程序自己定义的&quo ...
- Lua虚拟机中的数据结构与栈
Lua虚拟机中的数据结构与栈 来源 https://blog.csdn.net/zry112233/article/details/80828327 由上一篇文章可知解释器分析Lua文件之后生成Pro ...
- 深入浅出Lua虚拟机
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文后面分享的Demo代码都是我一行一 ...
- 大佬带你深入浅出Lua虚拟机
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由鹅厂优文发表于云+社区专栏 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文 ...
- 【OpenStack 虚拟机初始化user-data & Cloud-init】
示例: import httplib import json import base64 tenant_id='xxx' token='xxx' compute_host="xxx" ...
- TODO: Java虚拟机 初始化过程
Java虚拟机 初始化过程: 参考: https://www.cnblogs.com/bhlsheji/p/4017816.html 参考:https://blog.csdn.net/boling_c ...
- java: org.luaj.vm2.LuaError:XXX module not found lua脚本初始化出错
我遇到这个错误是因为在引用脚本目录时,设置错了位置.设置成脚本所在目录的上级目录. lua使用和加载初始化方法 在java中使用lua,使用需要引用 luaj-jse-2.0.2.jar 同时需要使用 ...
- java: org.luaj.vm2.LuaError:XXX module not found lua脚本初始化出错(转)
我遇到这个错误是因为在引用脚本目录时,设置错了位置.设置成脚本所在目录的上级目录. lua使用和加载初始化方法 在java中使用lua,使用需要引用 luaj-jse-2.0.2.jar 同时需要使用 ...
- ClassLoader机制:一个类何时会被虚拟机初始化?
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 大家都知道Java程序被编译器编译成字节码文件保存在硬盘里,Java虚拟机在执行代码时首先要把编译后的字节码文件从硬盘加载到内存中,然后才 ...
随机推荐
- IO密集型操作时,为什么线程比进程更好?
在IO密集型的操作时,进程线程都不会太占用CPU,但是进程消耗的资源比较多.
- Linux软连接和硬连接
软连接 命令: ln -s 原文件 目标文件 特征: 1.相当于windows的快捷方式 2.只是一个符号连接,所以软连接文件大小都很小 3.当运行软连接的时候,会根据连接指向找到真正的文件,然后执行 ...
- eclipse 修改 JDK中的src.zip的路径
http://blog.sina.com.cn/s/blog_54a1bca7010112fb.html http://www.douban.com/note/211369821/ 1.点 “wind ...
- Hive2.0的新特性介绍
- 【leetcode刷题笔记】Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...
- Docker 数据管理-Volumes
Volumes是Docker最为推荐的数据持久化方法. Volumes have several advantages over bind mounts: Volumes are easier to ...
- IE Firefox css 差别
1.单位问题 问题:任何距离的数值ie可以不加单位,ff必须要求写单位(0除外) 解决:写全单位如padding:0px; 2.水平居中 问题:div里的内容,ie默认为center,而ff默认lef ...
- JavaScript常用函数以及语法
$("#dwid").val(checkedVal.join(',')); .字符串(String) trim() //去掉空格 1.声明 var myString ...
- node Express安装和使用
1:在cmd命令行下执行npm install -g express,安装全局的express 2:进入需要创建项目的目录下执行express nodeExpressProject,创建express ...
- 列存储压缩技巧,除公共除数或者同时减去最小数,字符串压缩的话,直接去重后用数字ID压缩
Column-store compression At a high level, doc values are essentially a serialized column-store. As w ...