Deno 系统信息 API 的平台适配实现:以 deno_os 扩展为例解析 loadavg、hostname、mem_info 等跨平台系统调用 📅 发布时间:2026/9/5 17:16:09 👁 浏览次数: Deno 系统信息 API 的平台适配实现以 deno_os 扩展为例解析 loadavg、hostname、mem_info 等跨平台系统调用【免费下载链接】denoA modern runtime for JavaScript and TypeScript.项目地址: https://gitcode.com/GitHub_Trending/de/deno本篇围绕 Deno 仓库中的deno_os扩展crate 名为deno_os展开先完整继承其 README 中每个系统信息 API 在各平台分别调用哪个系统调用的对照表再结合 lib.rs、sys_info.rs 与 JS 侧 30_os.js 的源码讲清这些 API 从Deno命名空间一路落到libc/Win32 调用的完整链路、权限校验规则与错误处理细节读完可以复现 Deno 跨平台系统 API 的实现方式并自行扩展类似能力。1. deno_os 是什么一个 Rust 扩展 两段懒加载 JSdeno_oscrate 的职责在 Cargo.toml 中一句话概括OS specific APIs for Deno。它通过deno_core::extension!宏声明为一组 op 的集合注册入口在 lib.rsop 清单op_env、op_exec_path、op_exit、op_delete_env、op_get_env、op_gid、op_hostname、op_loadavg、op_network_interfaces、op_os_release、op_os_uptime、op_set_env、op_set_exit_code、op_system_memory_info、op_uid以及信号三件套op_signal_bind/op_signal_poll/op_signal_unbind实现在 ops/signal.rsJS 侧lazy_loaded_js [30_os.js, 40_signals.js]即两段脚本按需加载分别承载Deno系统信息/环境/退出相关方法与信号监听依赖核心依赖为deno_core、deno_permissions权限检查、deno_signals信号注册、libcUnix 系统调用Windows 目标额外引入windows-sys启用了Wdk_System_SystemServicesRtlGetVersion、Win32_Networking_WinSockGetHostNameW、Win32_System_ProcessStatus内存信息等 feature这些 feature 与后文各平台实现一一对应。这种Rust 实现 op JS 薄封装 权限容器的分层是 Deno 所有扩展的标准形态下文以 README 点名的五个 API 为主线逐一对比各平台的真实实现。2. loadavg负载平均值的三种取法README 给出的平台对照表如下完全继承原文档目标平台族使用的系统调用说明Linuxsysinfo-Windows-返回DEFAULT_LOADAVGWindows 上不存在 loadavg 概念macOS、BSDgetloadavg参见 FreeBSD 的 getloadavg 手册源码印证在 sys_info.rs 的loadavg()中三条编译分支与表格严格对应Linux/Androidlibc::sysinfo()成功后把info.loads[0..3]分别除以1 SI_LOAD_SHIFT还原为浮点负载值内核结构体里是以移位整数存储的Apple 与 FreeBSD/OpenBSDlibc::getloadavg(mut l, 3)返回值小于 3 时回退DEFAULT_LOADAVGWindows直接返回DEFAULT_LOADAVG (0.0, 0.0, 0.0)不做任何系统调用。op 层包装见 lib.rsop_loadavg先通过PermissionsContainer::check_sys(loadavg, Deno.loadavg())做权限检查再调用sys_info::loadavg()最终由 30_os.js 的loadavg()直接透传暴露为Deno.loadavg()返回长度为 3 的数组1 分钟、5 分钟、15 分钟负载。值得注意的边界行为任何系统调用失败都会静默回退为(0,0,0)而非抛错这使得在受限环境如部分容器中 API 仍然可用但取到的可能是兜底值。3. os_release内核/系统版本的四个分支README 对照表继承原文档目标平台族使用的系统调用说明Linux读取/proc/sys/kernel/osrelease-WindowsRtlGetVersion返回dwMajorVersion.dwMinorVersion.dwBuildNumbermacOSsysctl([CTL_KERN, KERN_OSRELEASE])-实际实现在 sys_info.rs 的os_release()比表格还多一个 Android 分支Linuxstd::fs::read_to_string(/proc/sys/kernel/osrelease)成功则pop()掉末尾换行失败返回空串Android表格未单列源码存在该分支libc::uname()取utsname.releasemacOS/BSDsysctl([CTL_KERN, KERN_OSRELEASE])固定 256 字节缓冲注释说明256 is enough失败返回字符串UnknownWindows调用 WDK 的RtlGetVersion填充OSVERSIONINFOEXW先初始化dwOSVersionInfoSize字段失败返回空串成功则格式化为主版本.次版本.构建号。op 入口op_os_releaselib.rs对应的权限项是osRelease。JS 侧 30_os.js 将其暴露为Deno.osRelease()。4. hostname缓冲区大小如何决定README 对照表继承原文档目标平台族使用的系统调用说明Unixgethostname(sysconf(_SC_HOST_NAME_MAX))-WindowsGetHostNameW-sys_info.rs 的hostname()展示了两种截然不同的缓冲区策略Unix先libc::sysconf(libc::_SC_HOST_NAME_MAX)向系统询问主机名的最大长度按buf_size 1分配缓冲区再调gethostname最后强制 NUL 终止并做 lossy 转码——即先问系统上限再精确分配Windows固定 256 个宽字符WCHAR缓冲区调用GetHostNameW。更隐蔽的一点是调用前必须通过WINSOCKET_INIT: Once先执行一次WSAStartup(0x0202, ...)MAKEWORD(2,2)否则GetHostNameW行为不正确启动失败会直接panic!。op 入口op_hostnamelib.rs对应Deno.hostname()权限项为hostname。5. mem_info系统内存信息的MemInfo结构Deno.systemMemoryInfo()返回的结构在 sys_info.rs 定义为 7 个u64字段total、free、available、buffers、cached、swap_total、swap_free通过ToV8派生直接转为 JS 对象。README 对照表继承原文档目标平台族使用的系统调用说明Linuxsysinfo和/proc/meminfo-Windowssysinfoapi::GlobalMemoryStatusEx-macOSsysctl([CTL_HW, HW_MEMSIZE])sysctl([CTL_VM, VM_SWAPUSAGE])host_statistics64(mach_host_self(), HOST_VM_INFO64)-各分支实现sys_info.rs 的mem_info()细节Linuxlibc::sysinfo()提供 totalram/freeram/bufferram/totalswap/freeswap并且所有值要乘以info.mem_unit较新内核中字段单位是mem_unit而非字节available不能从sysinfo得到需要额外读取/proc/meminfo的MemAvailable:行单位 kB乘 1024 转为字节——这正是 README 里sysinfo 和 /proc/meminfo两个来源的原因macOS物理内存来自sysctl([CTL_HW, HW_MEMSIZE])swap 总量/空闲来自sysctl([CTL_VM, VM_SWAPUSAGE])的xsw_usageavailable与free由 Mach 的host_statistics64(HOST_VM_INFO64)结合页大小计算其中available (free_count inactive_count) × pagesize、free (free_count - speculative_count) × pagesizeWindowsGlobalMemoryStatusEx只给出物理内存ullTotalPhys/ullAvailPhysswap 相关字段因MEMORYSTATUSEX.ullTotalPageFile不可靠源码转而调用GetPerformanceInfo用PageSize × (CommitLimit - PhysicalTotal)计算swap_total、再减去PhysicalAvailable得到swap_free。op 入口op_system_memory_infolib.rs对应权限项systemMemoryInfo返回OptionMemInfo成功时为Some。6. cpu_usage进程 CPU 时间的两个来源README 对照表继承原文档目标平台族使用的系统调用说明Linuxgetrusage-Windowsprocessthreadsapi::GetProcessTimes-macOSgetrusage-这段描述对应的是运行时进程级CPU 用量实现在 lib.rs 的op_runtime_cpu_usageget_cpu_usage()Unix含 Linux/macOSlibc::getrusage(libc::RUSAGE_SELF, ...)把ru_stime、ru_utime的秒/微秒分别合成DurationWindowsGetProcessTimes(GetCurrentProcess(), ...)取 kernel/userFILETIME再经FileTimeToSystemTime转换且对两个转换结果做了四象限容错任一失败则该侧回零其他平台源码中的兜底分支返回默认零值。op 以#[buffer] out: mut [f64]的形式把[sys, user]两个微秒值写回 JS 侧缓冲区避免了每次调用的对象分配。另有一个姊妹 opop_runtime_memory_usagelib.rs以同样方式写回 4 个值RSS、堆总量、已用堆、外部内存其中 RSS 按平台分别来自/proc/self/statmLinux、task_infomacOS、KERN_PROC_PIDsysctlOpenBSD、GetProcessMemoryInfoWindows。7. 从 op 到 Deno API权限检查与 JS 封装所有系统信息 op 都遵循同一模式先查sys权限子项再执行系统调用。以op_loadavg为例lib.rs第二个参数是用于报错提示的 API 名Deno.loadavg()。源码中可见的全部sys权限子项为loadavg、hostname、osRelease、networkInterfaces、systemMemoryInfo、gid、uid、osUptime它们都通过check_sys(子项, 提示)检查检查逻辑位于 runtime/permissions/lib.rs。因此用户可以以--allow-syshostname,osRelease这类粒度授权而不是整包放开系统信息。JS 侧 30_os.js 只是对每个 op 的一层薄封装loadavg()、hostname()、osRelease()、osUptime()、systemMemoryInfo()、networkInterfaces()、gid()、uid()等并在 lib.rs 的lazy_loaded_js中声明为懒加载脚本——只有真正触碰相关 API 时脚本才会被求值。8. 同 crate 的配套能力env、exit 与信号README 聚焦五个只读 API但同一个 crate 还承载了进程环境与生命周期管理简单补充Deno.envop_env/op_get_env/op_set_env/op_delete_envlib.rs实现了 key 校验空 key、含或 NUL 的 key、含 NUL 的 value 均抛TypeError类错误错误变体见OsError、权限检查以及一个静态互斥锁ProcessEnvGuard协调运行时对进程环境的访问修改TZ时会顺带调用tzset/_tzset并通知 V8 重新检测时区。tests/unit/os_test.ts 中的avoidEmptyNamedEnv、envToObjectKeysAreValid用例逐条验证了这些规则Deno.exitJS 侧先op_set_exit_code再派发unload事件最后op_exit()走 Rust 的exit(code)lib.rs在--watch模式下op_exit会改为终止当前 isolate 而非杀进程WatcherExitHandle信号监听40_signals.js 以addSignalListener/removeSignalListener管理监听集合首个监听者注册时才通过op_signal_bind创建信号资源最后一个移除时op_signal_unbind解绑Rust 侧 ops/signal.rs 用 tokiowatchchannel 把信号回调投递给异步的op_signal_poll资源关闭时调用deno_signals::unregister。9. 验证方式行为测试集中在 tests/unit/os_test.ts覆盖 env 的成功/缺省/删除/权限拒绝、非法 key/value 抛错、toObject()与get()的一致性含 Windows 下C:这类隐藏变量的回归测试以及系统信息 API 的调用Rust 侧自带单元测试lib.rs 用多线程 mpsc验证了ProcessEnvGuard在时区通知回调期间全程持有PROCESS_ENV_LOCKlib.rs 则保证 Node 环境变量白名单数组有序因为它依赖二分查找跳过权限检查权限矩阵测试可参考 tests/unit/permissions_test.ts 中对--allow-sys相关场景的断言。小结deno_os是 Deno 中把 OS 特定行为收敛到单一 crate的样板README 的五张平台×系统调用对照表loadavg / os_release / hostname / mem_info / cpu_usage在 sys_info.rs 与 lib.rs 中都有精确到cfg分支的对应实现且每个 API 都统一挂接sys权限子项检查与懒加载 JS 封装。理解这条JS API → op → 平台系统调用的链路后扩展或排查 Deno 的系统信息类 API 时可以直接按权限子项定位到对应的op_*函数与sys_info模块。【免费下载链接】denoA modern runtime for JavaScript and TypeScript.项目地址: https://gitcode.com/GitHub_Trending/de/deno创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考