Hive 浅析
Hive是一个简单的LUA沙盒,除了基本的LUA解释器的功能以外,还提供了诸如热加载等功能。 了解HIVE的工作原理有利于了解Lua虚拟机的底层实现机理。 本文从是什么-怎么用-为什么三个维度介绍HIVE。
Hive
Hive是什么
hive是一个简单的LUA应用框架,目前基于LUA 5.3.4。
主要提供了文件沙盒,文件热加载以及一些基础的服务程序底层支持.
HIVE源码:hive - master - gems / hive-framework - 工蜂内网版 (woa.com)
Hive的使用
编译
-
编译
luna# at the hive-framework root directorycd luna && makecp luan.so ../hive/ -
编译
hive# at the hive-framework root directorycd hive && make
运行
- 作为启动器的Hive
Hive本身只提供基础的热加载功能,并没有太多的功能。
你可以把Hive看作是一个简单的lua启动器,正如你使用lua file_name.lua一样,你也可以使用如下的命令行启动你的lua代码——
# make sure the lua binary is under your PATHhive file_name.lua# just like lua file_name.lua!
- 命令行参数
你也可以传递一些命令行参数进去,这些命令行参数会被打包放进一个表里,然后传递给你的脚本文件。
你可以使用hive.args在file_name.lua中来获取这些参数。
# ok,you can obtainhive file_name.lua arg1 arg2 arg3
例如在你自己的业务代码里,你可以写这样的代码:
-- print the args-- test.luafor k,v in ipairs(hive.args) doprint(string.format('%d:%s\n',k,v))end
保存为test.lua,然后在命令行中使用:
hive test.lua arg1 arg2 arg31:arg12:arg23:arg3
-
业务代码
被Hive启动的Lua的业务代码中,至少应该提供一个
hive.run的实现——--test.luahive.run = function()print('Hello world')Hive.run会被反复执行,效果如下所示——
hive test.luahello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello worldhello world...
除此以外,Hive还提供了一些feature,这些feature可以在Lua的环境中用,即,在你自己的业务代码中使用。
Hive的特性
本章从使用的角度介绍Hive的特性,如果需要详细了解实现原理,欢迎参阅源码剖析和Hive接口手册章节。
文件热加载
所谓文件热加载是指但凡使用import函数引入的文件(包括入口的文件,例如上面的test.lua)都会被Hive检测是否有更新。当Hive检测到文件时间戳改变以后,会自动重新进行读取。
请观察下面的示例——
-- test.lual = import('lobby.lua')hive.run = function() print('in test.lua')print('the imported l is:',l.str)hive.sleep_ms(2000);end
其中lobby.lua是另外一个lua程序
-- lobby.luastr = 'Yes, I am a lobby'
输入hive test.lua运行
hive test.luathe imported l is: Yes, I am a lobbyin test.luathe imported l is: Yes, I am a lobbyin test.luathe imported l is: Yes, I am a lobbyin test.lua...
在另外一个终端打开并修改lobby.lua文件,保存
--lobby.luastr = 'No!I am not a lobby!'
原终端中的输出发生改变
the imported l is: No, I am not a lobby!in test.luathe imported l is: No, I am not a lobby!in test.luathe imported l is: No, I am not a lobby!
沙盒环境
使用import导入的文件,Hive会为之创建了一个沙盒环境这使得各个文件中的变量名不会冲突。
下面的例子说明了import函数的行为——
-- lobby.luafunction m_add(a,b)return a + bend function m_sub(a,b)return a - bendreturn 1123
在test.lua中引入该文件:
l = import('lobby.lua')print(type(l))for k,v in pairs(l) doprint(k,':',v)end-- for k,v in pairs(_G) do-- print(k,':',v)-- endprint(l.m_add(1,2))print(l.m_sub(1000,2))
得到结果如下所示:可见,之前的定义都放在一个表中,且返回值被忽略了。
tablem_add : function: 0x228faa0m_sub : function: 0x229be803998
如果使用require,则有所不同
> require('lobby')1123> v = require('lobby')> m_addfunction: 0xa5c340> m_subfunction: 0xa5c010
有何不同?
如果使用自带的require函数,这里会有两个区别。
- 你可以获取到require的返回值
- 全局的作用域被影响,即这里的_G
本章节不涉及原理部分的阐述,如有需要,请参阅Hive接口手册。
源码剖析
热加载实现原理
这个主要和Hive::run代码有关:
...if(!lua_call_object_function(L, &err, this, "import", std::tie(), filename))die(err);while (lua_get_object_function(L, this, "run")) {if(!lua_call_function(L, &err, 0, 0))die(err);int64_t now = ::get_time_ms();if (m_reload_time > 0 && now > last_check + m_reload_time) {lua_call_object_function(L, nullptr, this, "reload");last_check = now;}lua_settop(L, top);}lua_close(L);}
- 首先将用户的代码(#2),使用
import函数进行加载。如果没有错,则继续进入一个循环。这个import函数,是Hive提前定义好的一个函数。后面还会介绍。 - 循环(#5)不断地从Lua环境中获取到Run函数的地址,然后去调用,如果获取不到函数地址,则循环直接中止,执行完毕。
- 否则则直接进行调用获取到的Run函数。
- 执行完毕以后,检查
import的文件是否有更新,如果有,则调用reload函数重新进行加载。
因此,我们可以说,如果业务代码中没有定义RUN函数,则系统会直接返回。
沙盒环境实现原理
所谓沙盒环境,其实就是不管怎么加载代码,都用一个table给装起来,而不污染全局的环境(详情可见上面的特性章节)。
沙盒的实现原理主要和Hive提前定义的load函数有关。
static const char* g_sandbox = u8R"__(hive.files = {};hive.meta = {__index=function(t, k) return _G[k]; end};hive.print = function(...) end; --do nothinglocal get_filenode = function(filename)local rootpath = os.getenv("LUA_ROOT");local withroot = rootpath and hive.get_full_path(rootpath).."/"..filename or filename;local fullpath = hive.get_full_path(withroot) or withroot;local node = hive.files[fullpath];if node thenreturn node;endlocal env = {};setmetatable(env, hive.meta);node = {env=env, fullpath=fullpath, filename=filename};hive.files[fullpath] = node;return node;endfunction import(filename)local node = get_filenode(filename);if not node.time thennode.time = hive.get_file_time(node.fullpath);try_load(node);endreturn node.env;endhive.reload = function()local now = os.time();local update = true;while update doupdate = false;for path, node in pairs(hive.files) dolocal filetime = hive.get_file_time(node.fullpath);if filetime ~= node.time and filetime ~= 0 and math.abs(now - filetime) > 1 thennode.time = filetime;update = true;try_load(node);endendendend)__";
上面的定义,是Hive在加载用户的文件之前会调用的。
主要关注import函数——
- 函数首先执行
get_filenode函数。该函数首先到全局的hive.files表中进行查找,如果找到了,则直接返回该node,这里的node,其实就是一个表,一个虚拟的沙箱。否则就新建一张表,这张表的元表是固定的hive.meta,即如果在该表中无法找到,则到_G中进行查找。这里的_G事实上就是导入的文件的环境。 - 如果是新导入的文件,则对其进行加载即可,记录下导入的时间(方便后面检查是否有更新)
Hive接口手册
除了前面章节中所提到的内容,Hive其实还有一些其他的接口暴露给了用户。使用hive.xxx即可访问。
| API | 作用 |
|---|---|
| get_version | 返回版本号 |
| get_file_time | 获取文件的修改时间 |
| get_full_path | 获取文件的绝对路径 |
| get_time_ms/get_time_ns | 获取当前的时间(Epoch格式) |
| sleep_ms | 睡眠 |
| daemon | 服务作为后台运行 |
相关文章:
Hive 浅析
Hive是一个简单的LUA沙盒,除了基本的LUA解释器的功能以外,还提供了诸如热加载等功能。 了解HIVE的工作原理有利于了解Lua虚拟机的底层实现机理。 本文从是什么-怎么用-为什么三个维度介绍HIVE。 Hive Hive是什么 hive是一个简单的LUA应用框架,目前基于…...
C 语言中,结构体「.」与「->」的区别
简单来说 「 」的左边是结构体名字时用点符号「.」 「 」的左边是结构体指针时名字时用箭头「->」 对于要读取结构体种的数据时,有下面三种写法,操作是等价的。 struct ListNode a;struct ListNode *p1 &a;/*三种写法*/a.element 2333;p1->e…...
【Java Web学习笔记】5 - XML
项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/xml 零、在线文档 XML系列教程 一、XML引出 1.为什么需要XML 1.需求1 :两个程序间进行数据通信? 2.需求2:给一台服务器,做一个配置文件,当服务器程序启动时,去…...
在jupyter notebook中修改其他文件的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
如何在Android中旋转屏幕时避免重新绘制Activity
如何在Android中旋转屏幕时避免重新绘制Activity 在Android开发中,设备旋转通常导致当前活动(Activity)被销毁并重新创建,这可能导致用户界面重置和不必要的资源重新加载。然而,有时我们希望避免这种行为,…...
离线环境下安装python库(推荐pip download)
离线环境下安装python库(推荐pip download) 目录 1.需求 2.失败操作(注意) 3.成功操作 4.其它参考 1.需求 机器部署web系统环境后,就不可再次联网,所以升级python web后端,需要离线安装pyt…...
ubuntu16.04安装ROS+Gazebo
ubuntu16.04安装ROS参考文章 ros安装(一键最简安装,吹爆鱼香ROS,请叫我鱼吹) ROS篇——Ubuntu快速一键安装ROS或ROS2(通用) ubuntu安装ROS melodic(最新、超详细图文教程) 配置ubuntu以及安装ros2必要环…...
手动搭建koa+ts项目框架(路由篇)
文章目录 前言一、安装koa-router二、引入koa-router并使用三、优化路由配置总结如有启发,可点赞收藏哟~ 前言 本文基于手动搭建koats项目框架(基础篇)配置接口路由 一、安装koa-router npm i -S koa-router二、引入koa-router并使用 ./sr…...
c语言:文件操作(1)
前言:为什么要使用文件 使用文件可以让程序在不同运行之间保存和读取数据。这样可以实现持久化存储,即使程序关闭后数据也不会丢失。文件也可以用于数据交换,允许不同程序之间共享信息。在 C 语言中,文件还可以用于读取配置信息&…...
运筹学经典问题(三):最大流问题
问题描述 给定一个图网络 G ( V , E ) G(V, E) G(V,E),网络中连边的权重代表最大容量,在这个图中找出从起点到终点流量最大的路径。 数学建模 集合: I I I:点的集合; E E E:边的集合。 常量&#x…...
裸机开发与Linux驱动开发的区别
一. 简介 裸机开发,即我们常说的不带系统的单片机开发。 Linux驱动开发,即带文件系统的Linux驱动的开发。 二. 裸机开发与Linux驱动开发的区别 1. 裸机开发 比较底层,跟寄存器打交道,有些 MCU提供了库。 2. Linux驱动开发…...
【蓝桥杯选拔赛真题75】Scratch行走的螃蟹 第十五届蓝桥杯scratch图形化编程 少儿编程创意编程选拔赛真题解析
目录 scratch行走的螃蟹 一、题目要求 编程实现 二、案例分析 1、角色分析...
小型洗衣机哪个牌子质量好?迷你洗衣机排名前十名
随着内衣洗衣机的流行,很多小伙伴在纠结该不该入手一款内衣洗衣机,专门来洗一些贴身衣物,答案是非常有必要的,因为我们现在市面上的大型洗衣机只能做清洁,无法对我们的贴身衣物进行一个高强度的清洁,而小小…...
MySQL_9.B-数索引
1.定义:B-树是一类树,包括B-树、B树、B*树等,是一棵自平衡的搜索树,它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点. 2.B-数产生的原因 当数据量非常大时,内存不够用,大部分数据只能存放在磁盘上,只有需要的…...
ubuntu-更改镜像源-系统初始化-安装Clion-C++编译环境-Java安装
文章目录 1.镜像配置文件及更新2.安装java sdk并配置环境变量3.安装Clion4.总结 1.镜像配置文件及更新 将sources.list备份保存为sources.list.backup,以防止有需要的时候更换回来。 sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup sudo gedit /etc/apt/source…...
c语言-动态内存管理
文章目录 一、为什么会有动态内存管理二、申请内存函数1、malloc2、free3、calloc4、realloc 三、常见的动态内存的错误四、练习 一、为什么会有动态内存管理 1.我们一般的开辟空间方式: int a 0;//申请4个字节空间 int arr[10] { 0 };//申请40个字节空间2.这样…...
【JAVA杂货铺】一文带你走进面向对象编程的构造方法 | Java| 面向对象编程 | (中)
🌈个人主页: Aileen_0v0🔥系列专栏:Java学习系列专栏💫个人格言:"没有罗马,那就自己创造罗马~" 目录 回顾 构造方法 this关键字 面试题 构造方法的类型 下节预告 代码块 🍒回顾 之前我们学习了什么是类 什么是…...
动态规划学习——通符串匹配,正则表达式
目录 编辑 一,通符串匹配 1.题目 2.题目接口 3,解题思路及其代码 二,正则表达 1.题目 2.题目接口 3.解题思路及其代码 三,交错字符串 1.题目 2,题目接口 3.解题思路及其代码 一,通符串匹配 1…...
【数据开发】Hive 多表join中的条件过滤与指定分区
1、条件过滤 left join 中 on 后面加条件 where 和 and 的区别 1、 on条件是在生成临时表时使用的条件,它不管and中的条件是否为真,都会保留左边表中的全部记录。2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有le…...
基于Java SSM框架实现高校人事管理系统项目【项目源码】计算机毕业设计
基于java的SSM框架实现高校人事管理系统演示 JSP技术介绍 JSP技术本身是一种脚本语言,但它的功能是十分强大的,因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时,它可以使显示逻辑和内容分开,这就极大的方便了用户的需…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
