【LuatOS】修改LuatOS源码为PC模拟器添加高精度时间戳库timeplus
0x00 缘起
LuatOS以及Lua能够提供微秒或者毫秒的时间戳获取工具,但并没有提供获取纳秒的工具。通过编辑LuatOS源码以及相关BSP源码,添加能够获取纳秒的timeplus库并重新编译,以解决在64位Windows操作系统中LuatOS模拟器获取纳秒的问题,其运行效果如下所示:
- getunixtime:获取
秒
时间戳字符串 - getmillisecond:获取
毫秒
时间戳字符串 - getmicrosecond:获取
微秒
时间戳字符串 - getnanosecond:获取
纳秒
时间戳字符串
0x01 方法
参照LuatOS官方文档,对timeplus
进行开发,其步骤如下:
- Git拉取LuatOS和PC模拟器源代码;
- 新增一个通用库的实例;
- 注册库函数;
- 验证库函数;
1 Git拉取LuatOS和PC模拟器源代码
使用Git命令拉取“LuatOS”项目和“LuatOS跑在PC上”两个项目到本地同级目录下,拉取命令如下:
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
的文件,文件内容如下:
#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
, 新增一行:
// TimePlus 能够取微秒
LUAMOD_API int luaopen_timeplus(lua_State *L);
修改luatos-soc-pc
代码库的port\luat_base_mini.c
, 在static const luaL_Reg loadedlibs[]
中 {NULL, NULL}};
之上添加一行代码:
{"timeplus", luaopen_timeplus},
4 验证库函数
在luatos-soc-pc
代码库中,运行文件:build_windows_64bit_msvc.bat
进行编译,输出文件在build
文件夹下,编译之前请确保编译工具已经配置可用。运行所编译的文件luatos-lua.exe
,在命令行中执行以下代码,并验证输出:
timeplus.getunixtime()
timeplus.getmillisecond()
timeplus.getmicrosecond()
timeplus.getnanosecond()
0x02 总结
针对LuatOS Windows模拟器不能提供纳秒时间戳的工具问题,通过添加自定义库timeplus并重新编译以使得模拟器具有输出纳秒时间戳的能力。值得注意的是,当前纳秒的获取方法仅适用与Windows,对于Linux以及其他操作系统,需要修改luat_lib_timeplus.c
的实现过程,以提供该功能。
0x03 资源
- LuatOS 添加自定义库和函数 官方文档
0x04 后记
- 己欲立而立人,己欲达而达人。