SerenityOSuptime命令详解:从 man 手册到内核时钟的完整链路
【免费下载链接】serenityThe Serenity Operating System 🐞项目地址: https://gitcode.com/GitHub_Trending/se/serenity
uptime是 SerenityOS 中一条用于查询系统已运行时间的标准命令行工具,其行为由 Base/usr/share/man/man1/uptime.md 这份 man 手册定义。本文以该手册为核心,结合 Userland/Utilities/uptime.cpp、Kernel/FileSystem/SysFS/Subsystems/Kernel/Uptime.cpp 与 AK/NumberFormat.cpp 等源码,讲清它的用法、输出格式与底层数据来源,帮助你既能直接上手使用,也能理解"一条命令"背后从用户态到内核态的完整实现链路。
命令概述
uptime在 SerenityOS 的 Shell 中直接输入即可运行,其作用是:以单行文本形式向 STDOUT 输出系统的运行状态信息,包括系统上线时间与已持续运行时长。
$ uptime 2024-01-24 06:23:27 up 4:20:00默认输出分为两个部分:
- 前半段
2024-01-24 06:23:27:当前系统时间(日期 + 时分秒); - 后半段
up 4:20:00:系统自启动以来已运行的时长,采用H:MM:SS的"数字时钟"格式(小时不足两位时省略前导零,如4:20:00)。
与 Linux/BSD 的uptime不同,SerenityOS 的默认输出末尾还会追加当前登录用户数(详见下文"登录用户统计"一节)。手册中标注的FIXME(见 Userland/Utilities/uptime.cpp)也提示:为了对齐 Linux 与 BSD,未来还计划输出系统负载均值(load averages),但当前内核尚未提供该数据。
命令行选项
uptime支持两个选项,均由 LibCore/ArgsParser.h 解析,定义于源码 Userland/Utilities/uptime.cpp:
| 短选项 | 长选项 | 功能 |
|---|---|---|
-p | --pretty | 仅输出运行时长,使用人类可读的自然语言格式 |
-s | --since | 仅输出系统上线的时间点,格式为yyyy-mm-dd HH:MM:SS |
两个选项的源码行为(Userland/Utilities/uptime.cpp):
- 当
-s生效时:用"当前时间戳减去运行秒数"反推出系统上线时刻,再通过 LibCore/DateTime 格式化为日期时间字符串; - 当
-p生效时:调用human_readable_time()输出自然语言时长; - 两者均未指定时:输出默认格式(当前时间 + 数字时钟时长 + 用户数)。
注意:-p与-s同时给出时,-s分支优先(源码中先判断output_since),-p会被忽略;二者互斥逻辑并未在参数解析层强制,属于使用时需留意的细节。
示例演示
默认输出
$ uptime 2024-01-24 06:23:27 up 4:20:00人类可读格式(-p)
$ uptime -p Up 2 minutes, 20 seconds系统上线时间(-s)
$ uptime -s 2024-01-24 06:23:27输出格式的源码实现
人类可读时长:human_readable_time()
-p使用的human_readable_time()定义于 AK/NumberFormat.cpp,其逻辑为:依次以 86400、3600、60 为除数分解出天数、小时、分钟、剩余秒数,再按"非零才输出 + 单复数后缀(day/days)"的规则拼接,例如:
140秒 →Up 2 minutes, 20 seconds90061秒 →1 day 1 hour 1 minute 1 second
一个值得注意的边界处理:若天、时、分均为 0,则即使秒数为 0 也会输出0 seconds,保证输出永不空白。
数字时钟格式:human_readable_digital_time()
默认输出末尾的4:20:00由 AK/NumberFormat.cpp 的human_readable_digital_time()生成:小时、分钟、秒分别以{:02}补零(小时为 0 时省略),最终形如H:MM:SS。
登录用户统计
默认模式(无选项)下,uptime会读取/var/run/utmp(一个 JSON 文件),以该文件对象中的条目数作为登录用户数,并根据数量输出单复数:
2024-01-24 06:23:27 up 4:20:00, 1 user 2024-01-24 06:23:27 up 4:20:00, 3 users该 JSON 文件由 Userland/Utilities/utmpupdate.cpp 维护——系统会话在登录/注销时通过utmpupdate -c/-d增删条目(详见utmpupdate的 man 手册 Base/usr/share/man/man1/utmpupdate.md)。同一机制也被 Userland/Utilities/w.cpp 的w命令复用。
底层原理:数据从内核到用户态
数据源头:SysFS 中的/sys/kernel/uptime
uptime的运行秒数并非自己计时,而是读取 SysFS 虚拟文件/sys/kernel/uptime(源码见 Userland/Utilities/uptime.cpp)。该文件由内核的 SysFS 子系统实时生成,实现位于 Kernel/FileSystem/SysFS/Subsystems/Kernel/Uptime.cpp:
ErrorOr<void> SysFSUptime::try_generate(KBufferBuilder& builder) { return builder.appendff("{}\n", TimeManagement::the().uptime_ms() / 1000); }即每次读取时,内核都会把TimeManagement维护的毫秒级运行时长(uptime_ms(),见 Kernel/Time/TimeManagement.cpp)除以 1000 后写出——因此uptime拿到的是自系统启动以来的总秒数,字符串转整数由AK::StringUtils::convert_to_uint()完成。
沙箱化访问:pledge 与 unveil
uptime启动后立即声明最小权限(Userland/Utilities/uptime.cpp):
pledge("stdio rpath"):只保留标准 I/O 与只读路径访问能力;unveil("/sys/kernel/uptime", "r")与unveil("/var/run/utmp", "r"):把可访问的文件系统路径收敛到仅这两个只读文件,随后unveil(nullptr, nullptr)锁定。
这体现了 SerenityOS 用户态工具"默认最小权限"的典型模式:即使工具被攻破,也几乎无路径可写、无额外文件可读。
时区与时间格式化
-s与默认输出中的时间字符串均通过 LibCore/DateTime 生成。-s分支计算since_timestamp = 当前时间戳 - 运行秒数后再格式化,因此输出的是系统当前时区下的上线时刻。
构建与运行环境
uptime属于 SerenityOS 的用户态基础工具集,随系统镜像一同编译,构建注册见 Userland/Utilities/CMakeLists.txt。使用前提:
- 它依赖内核 SysFS(
/sys/kernel/uptime)与/var/run/utmp,因此只能在 SerenityOS 系统内运行,不能直接移植到普通 Linux 主机; - 在 SerenityOS 的 Shell 中直接执行即可,无需额外安装或配置;
- 由于没有参数时依赖
utmp文件中的会话条目,-p/-s两种"仅读内核时钟"的模式在无登录会话的环境中也能正常工作。
小结
uptime默认输出"当前时间 + 运行时长(H:MM:SS)+ 登录用户数";-p输出自然语言时长,-s输出系统上线时刻;- 运行秒数来自内核 SysFS 节点
/sys/kernel/uptime,用户数来自/var/run/utmp; - 工具通过
pledge/unveil以最小权限运行,时长格式化由 AK 的human_readable_time/human_readable_digital_time完成。
手册原文位于 Base/usr/share/man/man1/uptime.md,源码位于 Userland/Utilities/uptime.cpp,感兴趣的读者可沿着这两处继续深入。
【免费下载链接】serenityThe Serenity Operating System 🐞项目地址: https://gitcode.com/GitHub_Trending/se/serenity
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考