跳转至

11 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、Air1601开发板一块

2、TYPE-C USB数据线一根

3、Air1601开发板和数据线的硬件接线方式为

  • Air1601开发板通过TYPE-C USB口连接TYPE-C USB 数据线,数据线的另外一端连接电脑的USB口;
  • 在 Air1601 开发板上丝印标注 USB1,为芯片烧录下载接口;
  • 若遇到因电脑 USB 端口供电不足导致的烧录失败,也可改用外部稳压电源通过开发板上的 VIN 引脚进行供电;

购买链接:Air1601开发板 多功能5寸RGB屏 支持AirUI 摄像头 代开发固件-淘宝网

三、软件环境

在开始实践本示例之前,先筹备一下软件环境:

1、Luatools工具

2、内核固件文件(底层 core 固件文件):

本demo开发测试时使用的固件为LuatOS-SoC_V1004_Air1601.soc,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试。

3、 luatos需要的脚本和资源文件

  • 脚本和资源文件点我,查看demo链接

  • lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件;

准备好软件环境之后,接下来查看如何烧录项目文件到 Air1601 开发板中,将本篇文章中演示使用的项目文件烧录到Air1601开发板中。

四、演示功能概述

本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)

六、日志展示

[2026-03-03 15:09:08.238][LTOS/N][000000000.017]:I/user.os_core ===== 开始os核心库API演示 =====
[2026-03-03 15:09:08.240][LTOS/N][000000000.017]:I/user.os.date ===== 开始os.date接口演示 =====
[2026-03-03 15:09:08.244][LTOS/N][000000000.017]:I/user.os.date 默认格式本地时间: Sat Jan  1 08:00:00 2000
[2026-03-03 15:09:08.246][LTOS/N][000000000.018]:I/user.os.date 自定义格式本地时间: 2000-01-01 08:00:00
[2026-03-03 15:09:08.250][LTOS/N][000000000.018]:I/user.os.date UTC时间: 2000-01-01 00:00:00
[2026-03-03 15:09:08.252][LTOS/N][000000000.018]:I/user.os.date 本地时间table: year=2000, month=1, day=1
[2026-03-03 15:09:08.256][LTOS/N][000000000.018]:I/user.os.date UTC时间table: year=2000, month=1, day=1
[2026-03-03 15:09:08.257][CAPP/N][000000000.019]:__wrap_free 272:invaild free address 0
[2026-03-03 15:09:08.264][LTOS/N][000000000.019]:I/user.os.date 指定时间戳格式化: 20241225 18:30:00
[2026-03-03 15:09:08.266][LTOS/N][000000000.019]:I/user.os.date ===== os.date接口演示完成 =====
[2026-03-03 15:09:08.270][LTOS/N][000000000.019]:I/user.os.time ===== 开始os.time接口演示 =====
[2026-03-03 15:09:08.271][LTOS/N][000000000.019]:I/user.os.time 当前时间戳: 946684800 
[2026-03-03 15:09:08.276][CAPP/N][000000000.019]:__wrap_free 272:invaild free address 0
[2026-03-03 15:09:08.282][LTOS/N][000000000.020]:I/user.os.time 指定时间的时间戳: 1735122600 
[2026-03-03 15:09:08.287][LTOS/N][000000000.020]:I/user.os.time 当前时间详细信息: year=2000, month=1, day=1
[2026-03-03 15:09:08.289][LTOS/N][000000000.020]:I/user.os.time ===== os.time接口演示完成 =====
[2026-03-03 15:09:08.291][LTOS/N][000000000.020]:I/user.os.difftime ===== 开始os.difftime接口演示 =====
[2026-03-03 15:09:08.300][CAPP/N][000000000.020]:__wrap_free 272:invaild free address 0
[2026-03-03 15:09:08.303][CAPP/N][000000000.020]:__wrap_free 272:invaild free address 0
[2026-03-03 15:09:08.308][LTOS/N][000000000.021]:I/user.os.difftime 时间点A (2024-01-01): 1704067200 
[2026-03-03 15:09:08.312][LTOS/N][000000000.021]:I/user.os.difftime 时间点B (2025-01-01): 1735689600 
[2026-03-03 15:09:08.315][LTOS/N][000000000.021]:I/user.os.difftime 时间差(B-A): 3.1622400000000e+07 
[2026-03-03 15:09:08.318][LTOS/N][000000000.021]:I/user.os.difftime 时间差(B-A): 366.000 
[2026-03-03 15:09:08.320][LTOS/N][000000000.021]:I/user.os.difftime 时间差(A-B): -3.1622400000000e+07 
[2026-03-03 15:09:08.321][LTOS/N][000000000.021]:I/user.os.difftime ===== os.difftime接口演示完成 =====
[2026-03-03 15:09:08.324][LTOS/N][000000000.022]:I/user.os.remove ===== 开始os.remove接口演示 =====
[2026-03-03 15:09:08.329][LTOS/N][000000000.023]:I/user.os.remove 创建测试文件成功: /os_test_delete.txt
[2026-03-03 15:09:08.331][LTOS/N][000000000.023]:I/user.os.remove 测试文件存在,准备删除
[2026-03-03 15:09:08.334][LTOS/N][000000000.024]:I/user.os.remove 文件删除成功
[2026-03-03 15:09:08.336][LTOS/N][000000000.024]:D/vfs fopen /os_test_delete.txt r not found
[2026-03-03 15:09:08.337][LTOS/N][000000000.024]:I/user.os.remove 删除验证通过,文件已不存在
[2026-03-03 15:09:08.339][LTOS/N][000000000.024]:I/user.os.remove ===== os.remove接口演示完成 =====
[2026-03-03 15:09:08.344][LTOS/N][000000000.024]:I/user.os.rename ===== 开始os.rename接口演示 =====
[2026-03-03 15:09:08.346][LTOS/N][000000000.025]:I/user.os.rename 创建源文件成功: /os_test_old.txt
[2026-03-03 15:09:08.350][LTOS/N][000000000.026]:I/user.os.rename 源文件存在,准备重命名
[2026-03-03 15:09:08.351][LTOS/N][000000000.026]:D/vfs fopen /os_test_new.txt r not found
[2026-03-03 15:09:08.353][LTOS/N][000000000.027]:I/user.os.rename 文件重命名成功: /os_test_old.txt -> /os_test_new.txt
[2026-03-03 15:09:08.357][LTOS/N][000000000.027]:D/vfs fopen /os_test_old.txt r not found
[2026-03-03 15:09:08.361][LTOS/N][000000000.027]:I/user.os.rename 原文件已不存在,重命名验证通过
[2026-03-03 15:09:08.363][LTOS/N][000000000.028]:I/user.os.rename 新文件存在验证通过: /os_test_new.txt
[2026-03-03 15:09:08.366][LTOS/N][000000000.028]:I/user.os.rename 测试文件已清理
[2026-03-03 15:09:08.368][LTOS/N][000000000.028]:I/user.os.rename ===== os.rename接口演示完成 =====
[2026-03-03 15:09:08.369][LTOS/N][000000000.028]:I/user.os_core ===== os核心库API演示全部完成 =====

七、注意事项

暂无