19 os操作系统
一、概述
os核心库提供了文件操作、时间日期处理、系统信息获取等核心功能。os 库提供的文件操作接口与 io 库、fatfs 库配合使用可以完成绝大多数文件级操作需求;
1.1 时间操作说明
os时间函数经常与 socket 核心库配合使用。通过网络 NTP 成功获取时间后,建议直接使用 os.date() 获取本地时间,而非 rtc.get()。
1.1.1 底层工作机制:
1、socket.sntp() 执行成功后,会通过 NTP_UPDATE 事件通知应用层;
2、os.date() 基于系统当前时间工作,自动处理时区转换和格式化输出;
3、rtc.get()/rtc.set() 直接操作硬件 RTC 寄存器,返回原始时间数据;
NTP 时间同步的完整流程
-- 方法1:使用网络时间设置 RTC,然后通过 os.date() 获取
local function ntp_time_handler()
-- 获取网络时间戳(可选)
local tm = socket.ntptm()
-- 使用 os.date() 获取格式化本地时间
log.info("本地时间", os.date("%Y-%m-%d %H:%M:%S"))
local t = os.date("*t")
log.info("时间详情", json.encode(t))
end
sys.subscribe("NTP_UPDATE", ntp_time_handler)
-- 方法2:直接使用 os.date() 获取当前系统时间
local function show_current_time()
-- 适用于系统时间已同步的场景
log.info("当前时间", os.date("%Y-%m-%d %H:%M:%S"))
end
show_current_time()
1.1.2 os.date 与 rtc.set/rtc.get 的核心区别
os.date:
1、基于系统时间戳,自动处理时区转换;
2、提供格式化输出,支持标准 C 库 strftime 格式;
3、默认返回本地时间,通过格式字符串前缀"!"可获取UTC时间;
rtc.set/rtc.get:
1、直接读写硬件 RTC 寄存器,返回原始时间数据;
2、重要:rtc.set() 只能设置UTC时间(0时区时间),不处理时区;
3、重要:rtc.get() 获取的也是UTC时间(0时区时间);
4、时区设置通过 rtc.timezone() 单独配置,不影响 rtc.get() 的返回值;
1.1.3 推荐使用 os.date 的原因
1、使用简单:一行代码获取格式化时间,如 os.date("%Y-%m-%d %H:%M:%S");
2、时区智能:自动应用系统时区设置,直接返回本地时间,无需关心 rtc.timezone() 配置;
3、格式丰富:支持完整的 strftime 格式规范,包括 %Y年、%m月、%d日等所有标准格式;
4、标准化:遵循 C 标准库规范,格式字符串与其他平台通用,代码可移植性强;
5、便于理解:提供直观的时间格式化输出,直接适合用户界面显示和日志记录;
1.1.4 UTC 时间与本地时间的详细说明
什么是 UTC 时间
1、UTC(协调世界时):全球统一的时间标准,不受任何时区影响,是国际标准时间;
2、特点:全球统一、无夏令时、常用于网络时间同步、日志记录等场景;
3、获取方式os.date("!*t")返回 UTC 时间的 table 格式,os.date("!%Y-%m-%d %H:%M:%S")返回 UTC 时间字符串;
什么是本地时间
1、本地时间:基于 UTC 时间加上当地时区偏移,反映用户所在地区的实际时间;
2、特点:包含时区信息、自动处理夏令时(如适用)、适合用户界面显示;
3、获取方式:os.date("*t")返回本地时间的 table 格式,os.date("%Y-%m-%d %H:%M:%S")返回本地时间字符串;
二、准备硬件环境
参考:硬件环境清单,准备以及组装好硬件环境。
三、软件环境
1、烧录工具 Luatools;
2、本demo开发测试时使用的固件为Air8101 V2010 版本固件,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;
3、LuatOS 需要的脚本和资源文件:脚本资源文件
4、lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;
准备好软件环境之后,接下来查看如何烧录项目文件到 Air8101 开发板 - luatos@air8101 - 合宙文档中心,将本篇文章中演示使用的项目文件烧录到 Air8101 开发板中。
准备好软件环境之后,接下来查看如何烧录项目文件到 Air8101 核心板使用说明 - luatos@air8101 - 合宙文档中心,将本篇文章中演示使用的项目文件烧录到 Air8101 核心板中。
四、演示功能概述
本demo是LuatOS os核心库的完整功能演示,按照官方API文档实现,展示了OS库中所有标准接口的使用方法。通过本演示项目,开发者可以快速掌握LuatOS中os核心库功能的使用。
4.1 主程序入口模块(main.lua)
1、初始化项目信息和版本号
2、初始化看门狗,并定时喂狗
3、启动一个循环定时器,每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况方便分析内存使用是否有异常
4、加载os_core_demo模块(通过require "os_core_demo")
5、最后运行sys.run()。
4.2 os核心库API演示模块(os_core_demo.lua)
4.2.1时间日期处理
1、os.date() - 格式化时间日期,支持strftime格式规范
2、os.time() - 获取Unix时间戳,支持自定义时间表
3、os.difftime() - 计算两个时间戳的差值
4.2.2 文件操作功能
1、os.remove() - 删除指定路径的文件
2、os.rename() - 重命名文件或移动文件
五、演示核心步骤
local function os_core_demo()
log.info("os_core", "===== 开始os核心库API演示 =====")
-- 1. 演示os.date接口 - 格式化时间日期功能
log.info("os.date", "===== 开始os.date接口演示 =====")
-- 获取默认格式的本地时间字符串
local default_time = os.date()
log.info("os.date", "默认格式本地时间:", default_time)
-- 获取指定格式的本地时间字符串
local formatted_time = os.date("%Y-%m-%d %H:%M:%S")
log.info("os.date", "自定义格式本地时间:", formatted_time)
-- 获取UTC时间字符串(使用!前缀)
local utc_time = os.date("!%Y-%m-%d %H:%M:%S")
log.info("os.date", "UTC时间:", utc_time)
-- 获取本地时间table(使用*t)
local local_table = os.date("*t")
log.info("os.date", "本地时间table:", "year=" .. local_table.year .. ", month=" .. local_table.month .. ", day=" .. local_table.day)
-- 获取UTC时间table(使用!*t)
local utc_table = os.date("!*t")
log.info("os.date", "UTC时间table:", "year=" .. utc_table.year .. ", month=" .. utc_table.month .. ", day=" .. utc_table.day)
-- 格式化指定时间戳
local specific_timestamp = os.time({year=2024, month=12, day=25, hour=10, min=30, sec=0})
local specific_time = os.date("%Y年%m月%d日 %H:%M:%S", specific_timestamp)
log.info("os.date", "指定时间戳格式化:", specific_time)
log.info("os.date", "===== os.date接口演示完成 =====")
-- 2. 演示os.time接口 - 获取时间戳功能
log.info("os.time", "===== 开始os.time接口演示 =====")
-- 获取当前时间戳
local current_timestamp = os.time()
log.info("os.time", "当前时间戳:", current_timestamp, "秒")
-- 从指定时间表获取时间戳
local specific_time = {
year = 2024,
month = 12,
day = 25,
hour = 10,
min = 30,
sec = 0
}
local specific_timestamp = os.time(specific_time)
log.info("os.time", "指定时间的时间戳:", specific_timestamp, "秒")
-- 获取当前时间的详细时间信息
local current_time_table = os.date("*t", current_timestamp)
log.info("os.time", "当前时间详细信息:", "year=" .. current_time_table.year .. ", month=" .. current_time_table.month .. ", day=" .. current_time_table.day)
log.info("os.time", "===== os.time接口演示完成 =====")
-- 3. 演示os.difftime接口 - 计算时间差功能
log.info("os.difftime", "===== 开始os.difftime接口演示 =====")
-- 获取两个时间点的时间戳
local time_a = os.time({year=2024, month=1, day=1, hour=0, min=0, sec=0})
local time_b = os.time({year=2025, month=1, day=1, hour=0, min=0, sec=0})
log.info("os.difftime", "时间点A (2024-01-01):", time_a, "秒")
log.info("os.difftime", "时间点B (2025-01-01):", time_b, "秒")
-- 计算时间差
local difference = os.difftime(time_b, time_a)
log.info("os.difftime", "时间差(B-A):", difference, "秒")
-- 转换为天数显示
local days = difference / (24 * 60 * 60)
log.info("os.difftime", "时间差(B-A):", string.format("%.3f", days), "天")
-- 计算负时间差
local negative_diff = os.difftime(time_a, time_b)
log.info("os.difftime", "时间差(A-B):", negative_diff, "秒")
log.info("os.difftime", "===== os.difftime接口演示完成 =====")
-- 4. 演示os.remove接口 - 文件删除功能
log.info("os.remove", "===== 开始os.remove接口演示 =====")
-- 首先创建一个测试文件用于删除
local test_file = "/os_test_delete.txt"
local file = io.open(test_file, "w")
if file then
file:write("这是用于测试os.remove的示例文件内容\n")
file:close()
log.info("os.remove", "创建测试文件成功:", test_file)
else
log.error("os.remove", "创建测试文件失败")
-- 继续演示,尝试删除可能存在的文件
end
-- 验证文件存在
if io.exists(test_file) then
log.info("os.remove", "测试文件存在,准备删除")
else
log.warn("os.remove", "测试文件不存在,将尝试删除操作")
end
-- 使用os.remove删除文件
local success, errmsg = os.remove(test_file)
if success then
log.info("os.remove", "文件删除成功")
-- 验证文件已删除
if not io.exists(test_file) then
log.info("os.remove", "删除验证通过,文件已不存在")
end
else
log.error("os.remove", "文件删除失败,错误信息:", errmsg or "未知错误")
end
log.info("os.remove", "===== os.remove接口演示完成 =====")
-- 5. 演示os.rename接口 - 文件重命名功能
log.info("os.rename", "===== 开始os.rename接口演示 =====")
-- 首先创建源文件
local old_file = "/os_test_old.txt"
local new_file = "/os_test_new.txt"
local file = io.open(old_file, "w")
if file then
file:write("这是用于测试os.rename的源文件内容\n")
file:close()
log.info("os.rename", "创建源文件成功:", old_file)
else
log.error("os.rename", "创建源文件失败")
-- 继续演示,尝试重命名可能存在的文件
end
-- 验证源文件存在
if io.exists(old_file) then
log.info("os.rename", "源文件存在,准备重命名")
else
log.warn("os.rename", "源文件不存在,将尝试重命名操作")
end
-- 清理目标文件(如果存在)
if io.exists(new_file) then
os.remove(new_file)
log.info("os.rename", "清理已存在的目标文件:", new_file)
end
-- 使用os.rename重命名文件
local success, errmsg = os.rename(old_file, new_file)
if success then
log.info("os.rename", "文件重命名成功:", old_file, "->", new_file)
-- 验证原文件不存在
if not io.exists(old_file) then
log.info("os.rename", "原文件已不存在,重命名验证通过")
end
-- 验证新文件存在
if io.exists(new_file) then
log.info("os.rename", "新文件存在验证通过:", new_file)
end
-- 清理测试文件
os.remove(new_file)
log.info("os.rename", "测试文件已清理")
else
log.error("os.rename", "文件重命名失败,错误信息:", errmsg or "未知错误")
-- 尝试清理源文件
if io.exists(old_file) then
os.remove(old_file)
end
end
log.info("os.rename", "===== os.rename接口演示完成 =====")
log.info("os_core", "===== os核心库API演示全部完成 =====")
end
sys.taskInit(os_core_demo)
六、日志展示
[2025-10-23 16:47:38.274][00000000.043] I/user.os_core ===== 开始os核心库API演示 =====
[2025-10-23 16:47:38.274][00000000.043] I/user.os.date ===== 开始os.date接口演示 =====
[2025-10-23 16:47:38.274][00000000.043] I/user.os.date 默认格式本地时间: Thu Oct 23 16:47:38 2025
[2025-10-23 16:47:38.274][00000000.044] I/user.os.date 自定义格式本地时间: 2025-10-23 16:47:38
[2025-10-23 16:47:38.274][00000000.044] I/user.os.date UTC时间: 2025-10-23 08:47:38
[2025-10-23 16:47:38.275][00000000.044] I/user.os.date 本地时间table: year=2025, month=10, day=23
[2025-10-23 16:47:38.275][00000000.044] I/user.os.date UTC时间table: year=2025, month=10, day=23
[2025-10-23 16:47:38.275][00000000.044] I/user.os.date 指定时间戳格式化: 2024年12月25日 10:30:00
[2025-10-23 16:47:38.275][00000000.044] I/user.os.date ===== os.date接口演示完成 =====
[2025-10-23 16:47:38.275][00000000.044] I/user.os.time ===== 开始os.time接口演示 =====
[2025-10-23 16:47:38.275][00000000.044] I/user.os.time 当前时间戳: 1761209258 秒
[2025-10-23 16:47:38.275][00000000.044] I/user.os.time 指定时间的时间戳: 1735093800 秒
[2025-10-23 16:47:38.275][00000000.045] I/user.os.time 当前时间详细信息: year=2025, month=10, day=23
[2025-10-23 16:47:38.276][00000000.045] I/user.os.time ===== os.time接口演示完成 =====
[2025-10-23 16:47:38.276][00000000.045] I/user.os.difftime ===== 开始os.difftime接口演示 =====
[2025-10-23 16:47:38.276][00000000.045] I/user.os.difftime 时间点A (2024-01-01): 1704038400 秒
[2025-10-23 16:47:38.276][00000000.045] I/user.os.difftime 时间点B (2025-01-01): 1735660800 秒
[2025-10-23 16:47:38.276][00000000.045] I/user.os.difftime 时间差(B-A): 3.162240e+07 秒
[2025-10-23 16:47:38.276][00000000.045] I/user.os.difftime 时间差(B-A): 366.000 天
[2025-10-23 16:47:38.276][00000000.045] I/user.os.difftime 时间差(A-B): -3.162240e+07 秒
[2025-10-23 16:47:38.276][00000000.045] I/user.os.difftime ===== os.difftime接口演示完成 =====
[2025-10-23 16:47:38.276][00000000.045] I/user.os.remove ===== 开始os.remove接口演示 =====
[2025-10-23 16:47:38.276][00000000.046] D/fs fopen os_test_delete.txt wb
[2025-10-23 16:47:38.278][00000000.047] I/user.os.remove 创建测试文件成功: /os_test_delete.txt
[2025-10-23 16:47:38.278][00000000.047] D/fs fopen os_test_delete.txt rb
[2025-10-23 16:47:38.279][00000000.048] I/user.os.remove 测试文件存在,准备删除
[2025-10-23 16:47:38.281][00000000.051] I/user.os.remove 文件删除成功
[2025-10-23 16:47:38.281][00000000.051] D/fs fopen os_test_delete.txt rb
[2025-10-23 16:47:38.282][00000000.051] D/vfs fopen /os_test_delete.txt r not found
[2025-10-23 16:47:38.282][00000000.051] I/user.os.remove 删除验证通过,文件已不存在
[2025-10-23 16:47:38.282][00000000.051] I/user.os.remove ===== os.remove接口演示完成 =====
[2025-10-23 16:47:38.282][00000000.052] I/user.os.rename ===== 开始os.rename接口演示 =====
[2025-10-23 16:47:38.282][00000000.052] D/fs fopen os_test_old.txt wb
[2025-10-23 16:47:38.284][00000000.054] I/user.os.rename 创建源文件成功: /os_test_old.txt
[2025-10-23 16:47:38.285][00000000.054] D/fs fopen os_test_old.txt rb
[2025-10-23 16:47:38.285][00000000.054] I/user.os.rename 源文件存在,准备重命名
[2025-10-23 16:47:38.285][00000000.054] D/fs fopen os_test_new.txt rb
[2025-10-23 16:47:38.286][00000000.055] D/vfs fopen /os_test_new.txt r not found
[2025-10-23 16:47:38.289][00000000.058] I/user.os.rename 文件重命名成功: /os_test_old.txt -> /os_test_new.txt
[2025-10-23 16:47:38.289][00000000.058] D/fs fopen os_test_old.txt rb
[2025-10-23 16:47:38.289][00000000.059] D/vfs fopen /os_test_old.txt r not found
[2025-10-23 16:47:38.290][00000000.059] I/user.os.rename 原文件已不存在,重命名验证通过
[2025-10-23 16:47:38.290][00000000.059] D/fs fopen os_test_new.txt rb
[2025-10-23 16:47:38.290][00000000.060] I/user.os.rename 新文件存在验证通过: /os_test_new.txt
[2025-10-23 16:47:38.294][00000000.063] I/user.os.rename 测试文件已清理
[2025-10-23 16:47:38.294][00000000.064] I/user.os.rename ===== os.rename接口演示完成 =====
[2025-10-23 16:47:38.295][00000000.064] I/user.os_core ===== os核心库API演示全部完成 =====
七、注意事项
暂无