在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
文件根据实现功能的不同,可以分为四部分:
1虚拟机运转的核心功能lapi.c C语言接口 lzio.c 输入流接口
2源代码解析以及预编译字节码
lcode.c 代码生成器 lundump.c 还原预编译的字节码
3内嵌库
lauxlib.c 库编写用到的辅助函数库 4可执行的解析器,字节码编译器
lua.c 解释器 意为lua虚拟机的当前状态。
阅读源代码的次序(从外到内)
首先、阅读外围的库是如何实现功能扩展的,这样可以熟悉Lua公开API。不必陷入功能细节。 Lua对外暴露的API可以说是一个对内部模块的一层封装,这个层次尚未触及核心,但可以对核心代码有个初步的了解。 垃圾收集将是最难的部分,可能会花掉最多的时间去理解细节。
Lua的C函数以堆栈的形式和Lua虚拟机交换数据,由一系列API从L中取出值,经过一番处理,压回L中的堆栈。 Lua栈给C函数留的默认空间很小,默认情况下只有20。当你要在Lua的栈上留下大量值时,务必用luaL_checkstack扩展堆栈。因为处于性能考虑,Lua和栈有关的API都是不检查栈溢出的情况的。 在实现上,UserData只是对象结构从TString换成了Udate。
Lua使用table作为统一的数据结构。 用 table来表示Lua中的一切数据结构是Lua语言的一大特色。 为了效率,Lua的官方实现,又把table的储存分为数组部分和哈希表部分。 Table按照Lua语言的定义,需要实现四种基本操作:读、写、迭代和获取长度。Lua中并没有删除操作,而仅仅是把对应键位的值设置为nil。 Table的数组部分操作和C语言数组没有什么不同,不需要特别处理。 Lua实现复杂数据结构,大量依赖给table附加一个元表(metatable)来实现。
你可以很容易的创建出一个Lua虚拟机对象,不同的Lua虚拟机之间的工作是线程安全的,因为一切和虚拟机相关的内存操作都被关联到虚拟机对象中,而没有利用任何其它共享变量。 Lua的虚拟机核心部分,没有任何的系统调用,是一个纯粹的黑盒子,正确的使用Lua,不会对系统造成任何干扰。这其中最关键的一点是,Lua让用户自行定义内存管理器,在创建Lua虚拟机时传入,这保证了Lua的整个运行状态是用户可控的。 从Lua的使用者的角度看,global_state 是不可见的。我们无法用公开的API取到它的指针,也不需要引用它。global_State里面有对主线程的引用,有注册表管理所有全局数据,有全局字符串表,有内存管理函数,有GC需要的把所有对象串联起来的相关信息,以及一切Lua在工作时需要的工作内存。 通过lua_newstate创建一个新的lua虚拟机时,第一块申请的内存将用来保存主线程和这个全局状态机。 Lua的实现尽可能的避免内存碎片,同时也减少内存分配和释放的次数。它采用了一个小技巧,利用一个LG结构,把主线程 lua_State 和 global_state 分配在一起。 lua是用longjmp处理与c互相函数调用的问题。
如果说C++式的面向对象编程是把一组函数绑定到特定数据类型上的话,那么闭包可以说是把一组数据绑定到特定函数上。 闭包是函数和upvalue的结合体。
参考: 《lua源码赏析》 如何学习 Lua VM 的源码?https://www.zhihu.com/question/20617406 《 Structure and Interpretation of Computer Programs 》
|
请发表评论