ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

WSL WslcContainerState 容器状态枚举详解:状态语义、查询 API 与状态机实现

2026/9/11 6:18:02 拓冰建站 浏览量
WSL WslcContainerState 容器状态枚举详解:状态语义、查询 API 与状态机实现 WSL WslcContainerState 容器状态枚举详解状态语义、查询 API 与状态机实现【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWslcContainerState是 WSLWindows Subsystem for Linux容器 SDKWslcSDK中用于描述容器生命周期状态的 C 枚举类型它贯穿容器从创建、启动、退出到删除的完整生命周期。本篇文章以官方 API 参考文档 WslcContainerState 为主体结合仓库中 SDK 头文件、会话/容器实现与单元测试为你讲清每个枚举值的语义、如何通过WslcGetContainerState查询状态以及底层状态机是如何驱动状态迁移的。读完本文你将能够在自己的 C/C 程序中正确判断容器状态并理解状态在 WSL 服务端内部的流转机制。1. 枚举定义与取值在 WSL 的 C APIwslcsdk.h中容器状态通过如下枚举表达typedef enum WslcContainerState { WSLC_CONTAINER_STATE_INVALID 0, WSLC_CONTAINER_STATE_CREATED 1, WSLC_CONTAINER_STATE_RUNNING 2, WSLC_CONTAINER_STATE_EXITED 3, WSLC_CONTAINER_STATE_DELETED 4, } WslcContainerState;各枚举值与语义对应如下枚举值值语义WSLC_CONTAINER_STATE_INVALID0无效/未知状态通常用作查询前的初始化占位值也用于标识未成功获取到的状态WSLC_CONTAINER_STATE_CREATED1容器已被创建但尚未启动对应 Docker 的 created 状态WSLC_CONTAINER_STATE_RUNNING2容器正在运行init 进程存活WSLC_CONTAINER_STATE_EXITED3容器已退出正常退出或被停止WSLC_CONTAINER_STATE_DELETED4容器已被删除对象即将失效1.1 定义在仓库中的多处落点这个枚举在仓库中并非只有一处它同时存在于 SDK 公共头文件与跨进程共享的 IDL 定义中保证 C API、C/WinRT API 与 WSL 服务端三方使用同一套取值C SDK 公共头src/windows/WslcSDK/wslcsdk.h#L303-L310这里同时声明了查询函数WslcGetContainerState服务端共享定义src/windows/service/inc/WSLCShared.idl#L121-L128使用WslcContainerStateInvalid/Created/Running/Exited/Deleted命名供 WSL 服务wslservice内部组件通过 MIDL 编译共享C API 层见 doc/docs/api-reference/cpp/enumerations/containerstate.mdCContainer::State()直接对WslcContainerState做强转static_cast底层取值保持一致Invalid0、Created1、Running2、Exited3、Deleted4。从源码结构看这种一处权威取值、多端共享的设计确保了 SDK 调用方与服务端记录的状态永远可以对齐不会出现语义漂移。2. 查询容器状态WslcGetContainerState枚举本身只是状态值的定义真正把它用起来的是 SDK 提供的查询函数STDAPI WslcGetContainerState(_In_ WslcContainer container, _Out_ WslcContainerState* state);参数类型方向说明containerWslcContainerin由WslcCreateContainer或WslcOpenContainer等得到的容器句柄stateWslcContainerState*out接收查询结果的输出参数返回值为HRESULTS_OK表示成功。典型用法见 WslcGetContainerState API 参考WslcContainerState state WSLC_CONTAINER_STATE_INVALID; HRESULT hr WslcGetContainerState(container, state); if (SUCCEEDED(hr)) { // 根据 state 进行分支处理 }注意在调用前先将state初始化为WSLC_CONTAINER_STATE_INVALID这是一个安全的防御性写法——即使调用失败输出值也处于一个明确的未知占位状态而不是未初始化的垃圾值。在 COM 服务端该查询最终落到WSLCContainer::GetStatesrc/windows/wslcsession/WSLCContainer.h#L319并由WSLCContainerImpl::State()直接返回内部维护的m_state字段。3. 实战用状态机驱动容器生命周期官方 端到端示例 给出了一个完整的生命周期流程创建会话 → 拉取镜像 → 创建容器 → 启动容器 → 等待 init 进程退出 → 清理。其中在清理阶段就使用状态枚举做了按状态决定行为的判定// 6. Wait for the init process to exit WslcProcess initProc nullptr; hr WslcGetContainerInitProcess(container, initProc); if (SUCCEEDED(hr)) { HANDLE exitEvent nullptr; if (SUCCEEDED(WslcGetProcessExitEvent(initProc, exitEvent))) { WaitForSingleObject(exitEvent, 30000); // 30-second timeout } INT32 exitCode 0; if (SUCCEEDED(WslcGetProcessExitCode(initProc, exitCode))) { printf(Process exited with code: %d\n, exitCode); } WslcReleaseProcess(initProc); } // 7. Clean up: 仅在容器仍处于 RUNNING 时才需要先 Stop WslcContainerState containerState WSLC_CONTAINER_STATE_INVALID; if (SUCCEEDED(WslcGetContainerState(container, containerState)) containerState WSLC_CONTAINER_STATE_RUNNING) { WslcStopContainer(container, WSLC_SIGNAL_SIGTERM, 10, nullptr); } WslcDeleteContainer(container, WSLC_DELETE_CONTAINER_FLAG_NONE, nullptr); WslcReleaseContainer(container); WslcTerminateSession(session); WslcReleaseSession(session);这段代码体现了一个关键工程实践对已退出的容器重复调用Stop没有意义服务端对此是 no-op因此先用WslcGetContainerState判断状态只有RUNNING才发送停止信号WSLC_SIGNAL_SIGTERM10 秒超时随后无条件删除并释放资源。这种先查状态、再执行操作的模式可以避免对容器做无效操作并降低竞态风险。C 侧同样可以做到官方 C 文档containerstate.md给出了强转比较的写法auto state container.State(); if (state static_castContainerState(2)) { // running }4. 底层状态机状态如何迁移理解枚举值只是第一步真正值得深入的是服务端WSLCContainerImpl中维护m_state的状态机逻辑它定义了哪些迁移是合法的、每个状态改变时系统会做什么。4.1 CommitState唯一的状态写入点所有状态迁移都收敛在WSLCContainerImpl::CommitStatesrc/windows/wslcsession/WSLCContainer.cpp#L3108-L3129__requires_lock_held(m_lock) void WSLCContainerImpl::CommitState(WSLCContainerState State, std::int64_t Time, std::optionalint ExitCode) noexcept { // N.B. A deleted container cannot transition back to any other state. WI_ASSERT(m_state ! WslcContainerStateDeleted); WSL_LOG( ContainerStateChange, TraceLoggingValue(static_castint(m_state), PreviousState), TraceLoggingValue(static_castint(State), NewState), TraceLoggingValue(m_id.c_str(), ID)); m_state State; m_stateGeneration; m_stateChangedAt Time; RecordEvent(WSLCStateToEventAction(State), Time, ExitCode); if (State WslcContainerStateRunning) { // The restarts start phase landed, so a later exit must auto-delete an --rm container again. m_restart.reset(); } }关键设计点终态约束代码通过断言WI_ASSERT保证已DELETED的容器不允许再迁移回任何其他状态——DELETED是状态机的终结态状态变更代际计数每次迁移m_stateGeneration配合m_stateChangedAt时间戳用于并发场景下检测状态是否发生了新一轮变化见 WSLCContainer.h#L278-L283 中的m_stateChangedAt、m_stateGeneration字段事件记账状态变更会调用RecordEvent记录一条容器事件action 由WSLCStateToEventAction(State)生成事件带有容器 ID、时间戳与可选退出码WSLCContainer.cpp#L1280-L1290这些事件最终进入EventStore供 Docker 事件流等消费方使用运行态副作用当状态变为RUNNING时会清除正在进行的 restart 事务标记m_restart.reset()确保先 stop 再 start的重启事务不会跨越状态机边界。4.2 事件驱动的迁移路径容器状态并非由调用方直接写死而是由运行事件驱动迁移。核心入口是WSLCContainerImpl::OnEventWSLCContainer.cpp#L1293-L1339Start 事件当收到与当前 transition 预期一致的 Start 事件时先断言当前状态为CREATED或EXITED然后CommitState(WslcContainerStateRunning, eventTime)即CREATED/EXITED → RUNNINGStop 事件进入OnStopped最终在停止流程中CommitState(WslcContainerStateExited, stopTime, exitCode)WSLCContainer.cpp#L1614即RUNNING → EXITED并携带退出码Destroy 事件若当前状态不是DELETED则CommitState(WslcContainerStateDeleted, eventTime)并释放运行时资源端口、挂载、进程等随后通知等待 init 进程退出的阻塞方。由此可以得到完整的合法状态迁移图INVALID ──(创建成功)──▶ CREATED ──(Start)──▶ RUNNING ──(Stop/退出)──▶ EXITED │ │ │ ▼ └────(Delete)──▶ DELETED(终态) CREATED ─────────(Delete)──────────▶ DELETED EXITED ──────────(Delete)──────────▶ DELETED此外RUNNING状态还关联一个活动保持activity hold机制UpdateActivityHoldLockHeld保证容器仅在RUNNING时持有活动引用从而让会话的虚拟机在容器运行期间保持存活防止空闲回收把正在运行的容器所在的 VM 关掉WSLCContainer.h#L240-L242。4.3 会话级的清理在会话层WSLCSession会定期擦除已删除的容器条目std::erase_if(m_containers, ... entry.second-State() WslcContainerStateDeleted)WSLCSession.cpp#L2498。也就是说DELETED不仅是对象内部的终态也是容器从会话容器表中被移除的前置条件。5. 测试验证状态机的行为契约仓库的单元测试对状态语义做了非常详尽的验证是理解枚举行为契约的最好参考。以 test/windows/WSLCTests.cpp#L7499 的ContainerState测试为核心再加上其他用例可以归纳出以下被测试固化的行为启动后为 RUNNINGWslcStartContainer成功返回后container.State()必须等于WslcContainerStateRunning如 WSLCTests.cpp#L1788、#L7537停止/退出后为 EXITED容器执行完 init 进程退出或Stop后状态迁移为WslcContainerStateExitedWSLCTests.cpp#L7565、#L7005对 EXITED 容器 Stop 是 no-op测试明确验证对已退出容器调用 Stop() 不会改变状态仍保持WslcContainerStateExitedWSLCTests.cpp#L7795-L7797——这正是前面实战示例中先查询状态再决定是否 Stop 的依据Kill 后为 EXITEDKill用例验证容器被强杀后同样进入EXITED并在列表中表现为 exitedWSLCTests.cpp#L7725-L7729创建后为 CREATED某些流程如创建后不立即启动会验证状态为WslcContainerStateCreatedWSLCTests.cpp#L6884、#L7826列表语义expectContainerList辅助函数将容器名 镜像 状态三元组与docker ps风格列表对齐确保每个状态都能正确暴露给上层查询WSLCTests.cpp#L7501。这些测试从黑盒层面把枚举的每个取值都变成了可验证的行为契约也让WslcGetContainerState的返回值有了明确预期。6. 小结与使用建议回到本文主题WslcContainerState是一个只有 5 个取值的小枚举但它在 WSL 容器 SDK 中扮演着生命周期路标的角色取值约定INVALID0 / CREATED1 / RUNNING2 / EXITED3 / DELETED4C 与 C API 取值完全一致查询方式通过WslcGetContainerState(container, state)获取调用前建议把输出变量初始化为WSLC_CONTAINER_STATE_INVALID状态机约束DELETED是终态不可逆CREATED/EXITED → RUNNING → EXITED → DELETED是主路径所有迁移统一走CommitState并在加锁下完成同时会记录事件、递增代际计数工程实践执行 Stop/Delete 等破坏性操作前先查询状态可避免对已退出容器做无效操作。如果你要开发基于 WSL 容器的编排或管理工具推荐进一步阅读 WslcGetContainerState API 参考、端到端示例 以及 C 侧的状态文档 ContainerState并对照 WSLCTests.cpp 中的状态用例来校验自己的实现行为。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考