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.pswp.cn/news/208567.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/208567.shtml
英文地址,請注明出處:http://en.pswp.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…