【LuatOS】修改LuatOS源码为PC模拟器添加高精度时间戳库timeplus

0x00 缘起

LuatOS以及Lua能够提供微秒或者毫秒的时间戳获取工具,但并没有提供获取纳秒的工具。通过编辑LuatOS源码以及相关BSP源码,添加能够获取纳秒的timeplus库并重新编译,以解决在64位Windows操作系统中LuatOS模拟器获取纳秒的问题,其运行效果如下所示:

  • getunixtime:获取时间戳字符串
  • getmillisecond:获取毫秒时间戳字符串
  • getmicrosecond:获取微秒时间戳字符串
  • getnanosecond:获取纳秒时间戳字符串

0x01 方法

参照LuatOS官方文档,对timeplus进行开发,其步骤如下:

  1. Git拉取LuatOS和PC模拟器源代码;
  2. 新增一个通用库的实例;
  3. 注册库函数;
  4. 验证库函数;

1 Git拉取LuatOS和PC模拟器源代码

使用Git命令拉取"LuatOS"项目和"LuatOS跑在PC上"两个项目到本地同级目录下,拉取命令如下:

bash 复制代码
git clone https://gitee.com/openLuat/LuatOS.git
git clone https://gitee.com/openLuat/luatos-soc-pc.git

2 新增一个通用库的实例

进入LuatOS源码文件夹lua/src/目录下,添加名为:luat_lib_timeplus.c的文件,文件内容如下:

c 复制代码
#include <lauxlib.h>
#include <lua.h>
#include <stdio.h>
#include <windows.h>

#include "luat_base.h"

// 获取当前时间的 Unix 时间戳(秒)
static int l_timeplus_getunixtime(lua_State *L) {
  FILETIME ft;
  ULARGE_INTEGER ull;
  GetSystemTimeAsFileTime(&ft);

  ull.LowPart = ft.dwLowDateTime;
  ull.HighPart = ft.dwHighDateTime;

  // 将 FILETIME 转换为 Unix 时间戳(秒)
  time_t unixTime = (ull.QuadPart / 10000000ULL) - 11644473600ULL;

  lua_pushinteger(L, unixTime);
  return 1;
}

// 获取当前时间的 Unix 时间戳(毫秒)
static int l_timeplus_getmillisecond(lua_State *L) {
  FILETIME ft;
  ULARGE_INTEGER ull;
  GetSystemTimeAsFileTime(&ft);

  ull.LowPart = ft.dwLowDateTime;
  ull.HighPart = ft.dwHighDateTime;

  // 将 FILETIME 转换为 Unix 时间戳(毫秒)
  uint64_t milliseconds = (ull.QuadPart / 10000ULL) - 11644473600000ULL;

  lua_pushinteger(L, milliseconds);
  return 1;
}

// 获取当前时间的 Unix 时间戳(微秒)
static int l_timeplus_getmicrosecond(lua_State *L) {
  FILETIME ft;
  ULARGE_INTEGER ull;
  GetSystemTimeAsFileTime(&ft);

  ull.LowPart = ft.dwLowDateTime;
  ull.HighPart = ft.dwHighDateTime;

  // 将 FILETIME 转换为 Unix 时间戳(微秒)
  uint64_t microseconds = (ull.QuadPart / 10ULL) - 11644473600000000ULL;

  lua_pushinteger(L, microseconds);
  return 1;
}

// 获取当前时间的 Unix 时间戳(纳秒)
static int l_timeplus_getnanosecond(lua_State *L) {
  FILETIME ft;
  ULARGE_INTEGER ull;
  GetSystemTimeAsFileTime(&ft);

  ull.LowPart = ft.dwLowDateTime;
  ull.HighPart = ft.dwHighDateTime;

  // 将 FILETIME 转换为 Unix 时间戳(纳秒)
  // 乘以100将100纳秒单位转换为纳秒
  uint64_t nanoseconds_since_epoch =
      (ull.QuadPart - 116444736000000000ULL) * 100ULL;

  lua_pushinteger(L, nanoseconds_since_epoch);
  return 1;
}

// 库函数注册表
#include "rotable2.h"
static const rotable_Reg_t reg_timeplus[] = {
    {"getunixtime", ROREG_FUNC(l_timeplus_getunixtime)},
    {"getmillisecond", ROREG_FUNC(l_timeplus_getmillisecond)},
    {"getmicrosecond", ROREG_FUNC(l_timeplus_getmicrosecond)},
    {"getnanosecond", ROREG_FUNC(l_timeplus_getnanosecond)},
    {NULL, ROREG_INT(0)}};

// 库的声明
LUAMOD_API int luaopen_timeplus(lua_State *L) {
  luat_newlib2(L, reg_timeplus);
  return 1;
}

3 注册库函数

修改LuatOS代码库的 luat/include/luat_libs.h, 新增一行:

c 复制代码
// TimePlus 能够取微秒
LUAMOD_API int luaopen_timeplus(lua_State *L);

修改luatos-soc-pc代码库的port\luat_base_mini.c, 在static const luaL_Reg loadedlibs[]{NULL, NULL}};之上添加一行代码:

c 复制代码
{"timeplus", luaopen_timeplus},

4 验证库函数

luatos-soc-pc代码库中,运行文件:build_windows_64bit_msvc.bat进行编译,输出文件在build文件夹下,编译之前请确保编译工具已经配置可用。运行所编译的文件luatos-lua.exe,在命令行中执行以下代码,并验证输出:

lua 复制代码
timeplus.getunixtime()
timeplus.getmillisecond()
timeplus.getmicrosecond()
timeplus.getnanosecond()

0x02 总结

针对LuatOS Windows模拟器不能提供纳秒时间戳的工具问题,通过添加自定义库timeplus并重新编译以使得模拟器具有输出纳秒时间戳的能力。值得注意的是,当前纳秒的获取方法仅适用与Windows,对于Linux以及其他操作系统,需要修改luat_lib_timeplus.c的实现过程,以提供该功能。

0x03 资源

0x04 后记

  • 己欲立而立人,己欲达而达人。
相关推荐
UWA6 小时前
Unreal开发痛点破解!GOT Online新功能:Lua全监控 + LLM内存可视化!
开发语言·lua·unreal
1nullptr6 小时前
Lua迭代器与泛型for
lua
半夏知半秋6 小时前
skynet debug_console控制台中debug指令使用
服务器·开发语言·学习·lua
h79971010 小时前
redis lua脚本(go)调用教程以及debug调试
redis·golang·lua
玩转C语言和数据结构3 天前
Lua下载和安装教程(附安装包)
lua·lua下载·lua安装教程·lua下载和安装教程·lua安装包
Arva .4 天前
HTTP Client
网络协议·http·lua
爱吃小胖橘4 天前
Lua语法(2)
开发语言·unity·lua
ellis19705 天前
LuaC API知识点汇总
unity·lua
爱吃小胖橘8 天前
Lua语法
开发语言·unity·lua
东方芷兰8 天前
JavaWeb 课堂笔记 —— 20 SpringBootWeb案例 配置文件
java·开发语言·笔记·算法·log4j·intellij-idea·lua