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 类进行结合时,它可以使显示逻辑和内容分开,这就极大的方便了用户的需…...
数字记忆保护新方案:GetQzonehistory让QQ空间数据备份不再困难
数字记忆保护新方案:GetQzonehistory让QQ空间数据备份不再困难 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字时代,我们的个人记忆越来越多地以数据形式存…...
【ComfyUI】Qwen-Image-Edit-F2P用于影视概念设计:快速生成角色面部概念图
ComfyUI Qwen-Image-Edit-F2P用于影视概念设计:快速生成角色面部概念图 1. 引言:当AI画笔遇见影视美术 想象一下这个场景:一部新剧的美术指导正在为“饱经风霜的西部枪手”这个角色发愁。导演想要一张能瞬间抓住观众眼球的脸,一…...
OpenClaw技能市场巡礼:Top5适合Phi-3-vision-128k-instruct的图文处理插件
OpenClaw技能市场巡礼:Top5适合Phi-3-vision-128k-instruct的图文处理插件 1. 为什么需要为多模态模型搭配专用技能? 去年我在尝试用OpenClaw处理一批产品截图时,发现一个有趣现象:当我把图片直接丢给普通文本模型时,…...
实测Claude 4.5 Opus重构“屎山”代码:手把手教你用AI给遗留项目做外科手术(附前后对比与单元测试生成)
实测Claude 4.5 Opus重构“屎山”代码:手把手教你用AI给遗留项目做外科手术(附前后对比与单元测试生成) 接手一个满是"祖传代码"的老旧项目,就像被丢进一座迷宫——变量命名像密码,函数逻辑像意大利面&…...
javaweb企业设备信息资讯展示网站
目录同行可拿货,招校园代理 ,本人源头供货商功能模块划分核心业务功能技术实现要点安全与维护项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作同行可拿货,招校园代理 ,本人源头供货商 功能模块划分 用户管理模块 用户注册与登…...
深度学习特征分解、SVD 与 PCA —— 矩阵的“质因数分解“(六)
1. 定位导航 本篇是第2章线性代数的终篇,覆盖三个最有力的矩阵分析工具:特征分解、奇异值分解(SVD)、主成分分析(PCA)。此外还包括三个辅助工具:Moore-Penrose 伪逆、迹运算、行列式。 这些工具贯穿深度学习的方方面面——PCA 用于数据预处理和降维,SVD 用于模型压缩…...
Java函数计算迁移避坑清单:12个被官方文档隐瞒的关键限制(含Classloader隔离失效实录)
第一章:Java函数计算迁移避坑清单:12个被官方文档隐瞒的关键限制(含Classloader隔离失效实录)Java函数计算(如阿里云FC、AWS Lambda Java Runtime)在迁移传统Spring Boot应用时,常因底层沙箱机制…...
3步构建企业级实时日志分析系统:从数据采集到智能告警
3步构建企业级实时日志分析系统:从数据采集到智能告警 【免费下载链接】DouyinLiveWebFetcher 抖音直播间网页版的弹幕数据抓取(2025最新版本) 项目地址: https://gitcode.com/gh_mirrors/do/DouyinLiveWebFetcher 在现代企业IT架构中…...
SEO 推广与传统广告推广有什么区别
SEO 推广与传统广告推广有什么区别 在当今的数字化时代,企业如何有效地推广自己的产品和服务成为了一个亟待解决的问题。两种常见的推广方式——SEO 推广与传统广告推广——各有优劣,企业需要根据自身的需求和市场环境进行选择。本文将详细探讨SEO推广和…...
亚马逊/Shopee关键词排名高就一定好?你可能陷入了“数据幻觉”
关键词排名高只说明“看得见”,不代表“卖得动”,更不等于“值得投”。理论锚点信息经济学信号噪音理论:排名只是表层信号,可能混杂品牌词截流等无关信息。SEO 搜索意图分类:信息型搜索不等于交易型搜索。一、误区揭露…...
