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.argsfile_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服务作为后台运行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/208567.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis Plus详解【一】

一、简介 MybatisPlus可以节省大量时间,所有的CRUD代码都可以自动化完成。MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 特性: 无侵入:只做增强不做改变&…

Windows 12 和 AI 计算机

据商业时报消息 ,微软计划于 2024 年 6 月发布Windows 12。 新版本的操作系统将伴随集成人工智能。 该数据基于广达首席执行官林百里和宏基陈杰森在中国台北医疗科技展上的发言。 虽然这篇文章没有直接引用微软高管的话,但它是根据他们的评论得出的结…

IDEA 社区版 add GitLab Account

问题 IntelliJ IDEA Community Edition 2023.3(社区版)在使用GitLab连接时,使用个人访问令牌出现报错,代码: GraphQL error:[No such type ProjectMember,so it cant be a fraggment condition,Field id doesnt exis…

2023年最新prometheus + grafana搭建和使用

一、安装prometheus 1.1 安装 prometheus官网下载地址 sudo -i mkdir -p /opt/prometheus #移动解压后的文件名到/opt/,并改名prometheus mv prometheus-2.45 /opt/prometheus/ #创建一个专门的prometheus用户: -M 不创建家目录, -s 不让登录 useradd…

Navicat 技术指引 | 适用于 GaussDB 分布式的数据迁移工具

Navicat Premium(16.3.3 Windows 版或以上)正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能,还提供强大的高阶功能(如模型、结…

单例模式---饿汉式、懒汉式

一、什么是单例模式 单例模式,指的是一个类中的对象只能有一个,它在内存中只会创建一次对象的设计模式。 二、饿汉式 public class SingleTon {// 私有的构造方法private SingleTon() {};// 1. 饿汉式private static SingleTon instance new SingleTon…

整数以及浮点数在内存中的存储

一.整数在内存当中的存储 数据在内存中是以十六进制补码的形式进行存储的。 原码表示法简单易懂,适用于乘法,但用原码表示的数进行加减运算比较复杂,当两数相加时,如果同号则数值相加,但是进行减法时要先比较绝对值的…

认知觉醒(六)

认知觉醒(六) 第二节 感性:顶级的成长竟然是“凭感觉” 人类生存于世,比拼的是脑力思维,但极少有人知道,我们的身体里还有一个更高级的系统,若能善用,成就非凡。 1941年,德军对英国本土进行…

Neo4j介绍

1、Neo4j介绍 Neo4j 是一个图数据库管理系统,它专注于存储和处理图形结构的数据。图数据库是一类特殊的数据库,用于有效地管理图形数据模型,其中数据以节点、关系和属性的形式存储。 2、Neo4j特点 图数据库: Neo4j 是一种 NoSQ…

目标检测器技术演进简史

引言 目标检测算法的发展已经取得了长足的进步,从早期的计算机视觉方法开始,通过深度学习达到了很高的准确度。在这篇博文中,我们将一起回顾一下这些算法的发展阶段以及现代目标检测系统中使用的主要方法。 我们首先回顾早期传统的目标检测…

大数据技术3:数据仓库的ETL和分层模型

前言:我们先了解一下数据仓库架构的演变过程。 1 、数据仓库定义 数据仓库是一个面向主题的(Subject Oriented)、集成的(Integrate)、相对稳定的(Non-Volatile)、反映历史变化(Time…

电商系统架构演进

聊聊电商系统架构演进 具体以电子商务网站为例, 展示web应用的架构演变过程。 1.0时代 这个时候是一个web项目里包含了所有的模块,一个数据库里包含了所需要的所有表,这时候网站访问量增加时,首先遇到瓶颈的是应用服务器连接数&a…

深入体验:山海鲸可视化软件的独特魅力

山海鲸可视化软件是一款功能强大的数据可视化工具,作为该软件的资深用户,我深感其独特的魅力和优势。下面,我将从软件特点、操作体验、数据交互和实际应用场景等方面,为大家详细介绍山海鲸可视化软件。 首先,山海鲸可视…

解决Eslint和Prettier关于三元运算符的冲突问题

三元运算符Prettier的格式化 三元运算符Eslint的格式要求 解决办法 // eslint加入配置,屏蔽标红报错indent: [error, 2, { ignoredNodes: [ConditionalExpression] }]效果

Nginx按指定格式记录访问日志

今天突然想起来一个日志的一个东西,因为拉项目无意中看到了日志文件的一些东西,现在不经常做后端了,加上其他的一些原因吧.有时候有些问题也没想太多,马马虎虎就过了,后来想想还是要记录一下这方面的处理过程吧: 一般我们作为开发人员关注的日志只是在应用程序层面的,我们称它…

LSTM_预测价格问题_keras_代码实操

0、问题描述 使用Bicton数据集,对close数据进行预测,使用60个数据点预测第61个数据点。 下载数据集:Bitcoin Historical Data 前期已经使用了MLP和RNN进行预测:这里 1、 没有写完,明天再写:)…

POJ 3735 Training little cats 动态规划(矩阵的幂)

一、题目大意 我们有N只猫&#xff0c;每次循环进行K次操作&#xff08;N<100&#xff0c;K<100&#xff09;&#xff0c;每次操作可有以下三种选择&#xff1a; 1、g i 给第i只猫1个食物 2、e i 让第i只猫吃完它所有的食物 3、s i j 交换第i和j只猫的食物。 求出M次…

JS自己定义数组扩展方法 求和 和 最大值、最小值

相信有小伙伴看到这一个标题可能会想&#xff1a;现在都可以自己写方法了吗&#xff1f;这么炸裂。没错我们是可以自己写方法的。 1.我们定义的这个方法&#xff0c;任何一个数组实例对象都可以使用 2.自定义的方法写到 数组.propertype身上 最大值 const arr [1,2,3,4]Array…

销售技巧培训之如何提高手机销售技巧

销售技巧培训之如何提高手机销售技巧 随着科技的迅速发展&#xff0c;手机已成为我们日常生活中不可或缺的一部分。作为一名手机销售员&#xff0c;了解手机销售技巧是必不可少的。本文将通过案例分析与实践&#xff0c;为你揭示手机销售的奥秘。 一、了解客户需求 在销售过程…

AWS Remote Control ( Wi-Fi ) on i.MX RT1060 EVK - 3 “编译 NXP i.MX RT1060”( 完 )

此章节叙述如何修改、建构 i.MX RT1060 的 Sample Code“aws_remote_control_wifi_nxp” 1. 点击“Import SDK example(s)” 2. 选择“MIMXRT1062xxxxA”>“evkmimxrt1060”&#xff0c;并确认 SDK 版本后&#xff0c;点击“Next>” 3. 选择“aws_examples”>“aw…