WSL 容器 SDK C 接口 WslcGetProcessState 详解:查询 WSL 容器进程运行状态

📅 发布时间:2026/9/10 7:09:03
WSL 容器 SDK C 接口 WslcGetProcessState 详解:查询 WSL 容器进程运行状态
WSL 容器 SDK C 接口 WslcGetProcessState 详解查询 WSL 容器进程运行状态【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWslcGetProcessState是 WSL Container SDKWSLC SDK中用于查询容器内 Linux 进程运行状态的核心 C API调用方通过一个WslcProcess句柄即可获取进程当前所处的状态运行中、已退出、被信号终止或未知。本文将结合该 API 在 wslcsdk.h 中的声明、wslcsdk.cpp 中的实现以及 WslcSdkTests.cpp 中的测试用例深入讲解其签名、状态枚举语义、底层实现原理与实战用法帮助开发者在 WSL 容器生命周期管理中正确地进行进程状态轮询与退出判定。函数签名WslcGetProcessState的原型定义如下见 wslcsdk.hSTDAPI WslcGetProcessState(_In_ WslcProcess process, _Out_ WslcProcessState* state);参数类型方向说明processWslcProcessin有效的 WSL 容器进程句柄通常由WslcCreateContainerProcess或WslcGetContainerInitProcess返回stateWslcProcessState*out输出参数接收进程当前状态该枚举在 wslcprocessstate.md 中有完整定义返回值HRESULTS_OK表示查询成功失败时返回对应的错误码详见下文返回值与错误处理。该函数已通过 wslcsdk.def 导出为 SDK 公共符号属于 WSLC SDK 的进程管理PROCESS MANAGEMENT接口组与之并列的还包括WslcGetProcessPid、WslcGetProcessExitEvent、WslcGetProcessExitCode、WslcSignalProcess、WslcGetProcessIOHandle与WslcReleaseProcess完整清单见 Process APIs 索引。WslcProcessState 状态枚举语义WslcGetProcessState的输出由WslcProcessState枚举描述其定义位于 wslcsdk.htypedef enum WslcProcessState { WSLC_PROCESS_STATE_UNKNOWN 0, WSLC_PROCESS_STATE_RUNNING 1, WSLC_PROCESS_STATE_EXITED 2, WSLC_PROCESS_STATE_SIGNALLED 3 } WslcProcessState;枚举值数值语义WSLC_PROCESS_STATE_UNKNOWN0状态未知。SDK 实现会将输出初始化为该值仅在调用成功但无法获得明确状态时出现WSLC_PROCESS_STATE_RUNNING1进程正在运行尚未触发退出事件WSLC_PROCESS_STATE_EXITED2进程已正常退出可通过WslcGetProcessExitCode获取退出码WSLC_PROCESS_STATE_SIGNALLED3进程被信号如SIGKILL、SIGTERM终止值得注意的一点SDK 公共头文件中的该枚举与 WSL 服务内部 IDL 定义的WSLCProcessState见 WSLCShared.idl在数值上严格一致。实现中通过static_assert强制保证两者恒等见 wslcsdk.cpp确保公共 API 层与内部服务层的状态值可以安全互转。返回值与错误处理WslcGetProcessState返回HRESULT可能的值包括S_OK查询成功state被写入有效状态值E_POINTER传入的state为nullptr或process句柄为nullptrHRESULT_FROM_WIN32(ERROR_INVALID_STATE)process句柄有效但内部进程对象已被释放internalType-process为空即句柄处于悬空状态。从实现代码wslcsdk.cpp可以看到严格的三段式校验流程STDAPI WslcGetProcessState(_In_ WslcProcess process, _Out_ WslcProcessState* state) try { static_assert(/* 公共枚举与服务内部枚举数值一致 */); auto internalType CheckAndGetInternalType(process); // process 为 null → 抛 E_POINTER RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType-process); RETURN_HR_IF_NULL(E_POINTER, state); // state 为 null → 返回 E_POINTER *state WSLC_PROCESS_STATE_UNKNOWN; // 先初始化为 UNKNOWN WSLCProcessState runtimeState{}; int exitCode{}; RETURN_IF_FAILED(internalType-process-GetState(runtimeState, exitCode)); *state static_castWslcProcessState(runtimeState); return S_OK; } CATCH_RETURN();其中CheckAndGetInternalType会把不透明的WslcProcess句柄转换为内部类型WslcProcessImpl其核心成员是wil::com_ptrIWSLCCompatProcess process见 WslcsdkPrivate.h真正的状态查询最终委托给 COM 对象IWSLCCompatProcess::GetState。句柄的重新解释转换定义在 WslcsdkPrivate.cpp。底层实现原理退出事件驱动的状态判定WslcGetProcessState并不向容器内发送任何探测消息而是由 WSL 服务侧的进程控制对象根据退出事件是否已被触发来判定状态。核心逻辑位于 WSLCProcessControl.cppstd::pairWSLCProcessState, int WSLCProcessControl::GetState() const { if (m_exitEvent.is_signaled()) { WI_ASSERT(m_exitedCode.has_value()); return {WslcProcessStateExited, m_exitedCode.value()}; } else { return {WslcProcessStateRunning, -1}; } }解读这段实现可以得到两个关键事实状态由m_exitEvent决定m_exitEvent是一个wil::unique_event采用手动复位ManualReset模式见 WSLCProcessControl.h。退出事件未触发 → 判定为RUNNING退出事件已触发 → 判定为EXITED。退出码与状态同步维护m_exitedCode是std::optionalint进程退出码通过SetExitCode记录仅记录首个退出码后续写入被忽略并由SignalExit触发退出事件。对于容器被直接释放如--rm容器在销毁事件中才补发 init 退出信号或仍在运行即被强制拆除的场景WSLCProcessControl会合成128 SIGKILL作为退出码见 WSLCProcessControl.cpp。此外同一底层状态的消费方不止WslcGetProcessState一处。比如RunningWSLCProcess::GetExitCode见 WSLCProcessLauncher.cpp会先查询状态只有状态为EXITED或SIGNALLED时才返回退出码否则抛出ERROR_INVALID_STATE——这与WslcGetProcessExitCode的行为保持一致见下文。与其他进程管理 API 的组合使用WslcGetProcessState通常不单独使用而是与以下 API 配合完成完整的进程生命周期管理全部列于 Process APIs 索引API作用与状态查询的关系WslcGetProcessExitEvent获取进程退出事件句柄HANDLE见 wslcgetprocessexitevent.md比轮询更高效用WaitForSingleObject等待事件避免忙等WslcGetProcessExitCode获取进程退出码见 wslcgetprocessexitcode.md仅当状态为EXITED/SIGNALLED时调用才返回S_OKWslcSignalProcess向进程发送信号SIGHUP/SIGINT/SIGQUIT/SIGKILL/SIGTERM见 wslcsignalprocess.md发送信号后可调用本函数确认进程状态迁移WslcGetProcessPid获取容器内进程 PID状态为RUNNING时 PID 有效WslcReleaseProcess释放进程句柄释放后句柄失效再调用本函数将返回ERROR_INVALID_STATE关于退出码的一个重要约束WslcGetProcessExitCodewslcsdk.cpp在进程仍在运行时会返回HRESULT_FROM_WIN32(ERROR_INVALID_STATE)同时把退出码输出初始化为-1。因此典型判程范式是先调用WslcGetProcessState确认状态已离开RUNNING再读取退出码避免拿到无意义的中间值。完整实战示例轮询等待进程退出以下示例完整演示了从创建进程、轮询状态到读取退出码的完整流程可在遵循 SDK 初始化的前提下直接套用#include windows.h #include wslcsdk.h HRESULT WaitForProcessAndGetExitCode(WslcProcess process, INT32* finalExitCode) { // 1. 初始化输出 *finalExitCode -1; // 2. 轮询进程状态直到离开 RUNNING for (;;) { WslcProcessState state WSLC_PROCESS_STATE_UNKNOWN; HRESULT hr WslcGetProcessState(process, state); if (FAILED(hr)) { return hr; } if (state WSLC_PROCESS_STATE_RUNNING) { // 进程仍在运行短暂休眠后重试 Sleep(100); continue; } // 3. 状态已变为 EXITED 或 SIGNALLED读取退出码 INT32 exitCode 0; hr WslcGetProcessExitCode(process, exitCode); if (FAILED(hr)) { // 仍可能因竞态返回 ERROR_INVALID_STATE可重试或记录状态 return hr; } *finalExitCode exitCode; return S_OK; } }更推荐的做法是用WslcGetProcessExitEvent获取退出事件句柄并阻塞等待从根本上消除轮询开销WslcProcessState state WSLC_PROCESS_STATE_UNKNOWN; HRESULT hr WslcGetProcessState(process, state); // 文档示例中的最小调用形式上面的最小调用形式初始化state为WSLC_PROCESS_STATE_UNKNOWN后传入也正是 wslcgetprocessstate.md 官方文档给出的示例写法。测试用例验证的行为约定SDK 自带的集成测试 WslcSdkTests.cpp 的ProcessGetState用例完整验证了本 API 的关键行为是理解语义最直接的参考WSLC_TEST_METHOD(ProcessGetState) { // 准备在 debian:latest 容器中启动 /bin/sleep 99 作为 init 进程 WslcProcessSettings procSettings; VERIFY_SUCCEEDED(WslcInitProcessSettings(procSettings)); const char* argv[] {/bin/sleep, 99}; VERIFY_SUCCEEDED(WslcSetProcessSettingsCmdLine(procSettings, argv, ARRAYSIZE(argv))); WslcContainerSettings containerSettings; VERIFY_SUCCEEDED(WslcInitContainerSettings(debian:latest, containerSettings)); VERIFY_SUCCEEDED(WslcSetContainerSettingsInitProcess(containerSettings, procSettings)); UniqueContainer container; VERIFY_SUCCEEDED(WslcCreateContainer(m_defaultSession, containerSettings, container, nullptr)); VERIFY_SUCCEEDED(WslcStartContainer(container.get(), WSLC_CONTAINER_START_FLAG_NONE, nullptr)); UniqueProcess process; VERIFY_SUCCEEDED(WslcGetContainerInitProcess(container.get(), process)); HANDLE exitEvent nullptr; VERIFY_SUCCEEDED(WslcGetProcessExitEvent(process.get(), exitEvent)); // 运行中状态为 RUNNING退出码读取应失败 WslcProcessState state{}; VERIFY_SUCCEEDED(WslcGetProcessState(process.get(), state)); VERIFY_ARE_EQUAL(state, WSLC_PROCESS_STATE_RUNNING); INT32 exitCode{}; VERIFY_ARE_EQUAL(WslcGetProcessExitCode(process.get(), exitCode), HRESULT_FROM_WIN32(ERROR_INVALID_STATE)); VERIFY_ARE_EQUAL(exitCode, -1); // SIGKILL 后等待退出事件状态应为 SIGNALLED 或 EXITED VERIFY_SUCCEEDED(WslcSignalProcess(process.get(), WSLC_SIGNAL_SIGKILL)); VERIFY_ARE_EQUAL(WaitForSingleObject(exitEvent, 30 * 1000), static_castDWORD(WAIT_OBJECT_0)); WslcProcessState state2{}; VERIFY_SUCCEEDED(WslcGetProcessState(process.get(), state2)); VERIFY_IS_TRUE(state2 WSLC_PROCESS_STATE_SIGNALLED || state2 WSLC_PROCESS_STATE_EXITED); // 负向用例null 输出指针 / null 进程句柄均返回 E_POINTER VERIFY_ARE_EQUAL(WslcGetProcessState(process.get(), nullptr), E_POINTER); WslcProcess nullProcess nullptr; WslcProcessState state3{}; VERIFY_ARE_EQUAL(WslcGetProcessState(nullProcess, state3), E_POINTER); }该用例验证了四个约定运行中状态容器启动后、进程存活期间WslcGetProcessState返回WSLC_PROCESS_STATE_RUNNING退出码语义运行中调用WslcGetProcessExitCode返回ERROR_INVALID_STATE且退出码被置为-1佐证了先查状态、再取退出码的调用顺序信号终止后的状态SIGKILL后等待退出事件被触发状态变为SIGNALLED或EXITED二者之一——这是因为服务侧对被信号终止与已退出的最终呈现存在容器运行时的差异调用方应同时接受这两种状态参数校验state为nullptr、process为nullptr时均返回E_POINTER与实现中的校验逻辑吻合。WinRT 与高级语言封装对于使用 WinRT/C# 的开发场景SDK 在 Process.cpp 中提供了Process::State()封装内部直接调用本函数并做 HRESULT 检查winrt::Microsoft::WSL::Containers::ProcessState Process::State() { WslcProcessState state; winrt::check_hresult(WslcGetProcessState(ToHandle(), state)); return static_castwinrt::Microsoft::WSL::Containers::ProcessState(state); }其中ToHandle()Process.cpp会先校验进程已启动未启动时抛出hresult_illegal_method_call这与 C API 层进程对象缺失返回ERROR_INVALID_STATE的错误语义一脉相承。注意事项与最佳实践不要在退出事件已触发后继续持有进程句柄WslcReleaseProcess释放后任何WslcGetProcessState调用都会返回ERROR_INVALID_STATE因此状态查询应放在释放句柄之前完成。状态轮询要有退避如需轮询建议结合WslcGetProcessExitEvent使用事件等待如测试中的WaitForSingleObject(exitEvent, 30 * 1000)而不是高频忙等以降低对 WSL 服务侧进程控制对象的压力。区分EXITED与SIGNALLED被信号终止的进程最终状态可能是两者之一业务逻辑应把二者统一视为进程已终止并配合退出码如128 signal惯例判断终止原因。先初始化输出调用前将state初始化为WSLC_PROCESS_STATE_UNKNOWN官方示例即如此即使调用失败也不会读到未定义值——SDK 内部同样会在写入前先做初始化双重保险。预览版 API 的稳定性声明WSLC SDK 头文件wslcsdk.h明确标注该 API 处于预览阶段签名与行为可能在不预先通知的情况下变更请勿将其作为生产环境的关键依赖。参考链接API 文档WslcGetProcessStateAPI 文档WslcProcessState 枚举Process APIs 完整索引SDK 公共头文件 wslcsdk.hSDK 实现 wslcsdk.cpp服务侧进程控制 WSLCProcessControl.cpp内部状态枚举 WSLCShared.idl集成测试 WslcSdkTests.cpp【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考