资讯动态

WSL WSLC C API 详解:WslcGetProcessPid 进程 PID 查询接口

发布时间:2026/9/10 16:16:40 来源:尧图企业网站定制
WSL WSLC C API 详解:WslcGetProcessPid 进程 PID 查询接口【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWslcGetProcessPid是 WSLWindows Subsystem for LinuxWSLC 容器 C API 中用于查询容器内进程 PID 的核心接口。本文围绕该 API 的函数签名、参数语义、返回值与错误处理展开,结合 WSL 仓库中 SDK 层的真实实现wslcsdk.cpp、底层WSLCProcess调用链、WinRT 投影封装以及单元测试用例,帮助读者在理解接口契约的同时掌握其底层原理与正确用法,能够在自己的 WSL 容器宿主程序中直接落地使用。一、API 定位:WSLC 进程管理接口中的进程身份查询WSLCWSL Containers是 WSL 提供的容器运行时基础设施,宿主程序通过一组 C API 创建、启动、管理与监控 Linux 容器及其中的进程。在 process-apis 索引 下共定义了一组围绕进程的接口,大体可分为三类:进程创建与设置:WslcCreateContainerProcess、WslcInitProcessSettings、WslcSetProcessSettingsCmdLine、WslcSetProcessSettingsWorkingDirectory、WslcSetProcessSettingsEnvVariables、WslcSetProcessSettingsCallbacks;进程运行与管理:WslcSignalProcess、WslcGetProcessExitEvent、WslcGetProcessIOHandle;进程状态与结果查询:WslcGetProcessPid、WslcGetProcessState、WslcGetProcessExitCode、WslcReleaseProcess。WslcGetProcessPid属于第三类查询接口,其职责是:给定一个由 WSLC 管理的进程句柄WslcProcess,返回该进程在 Linux 命名空间内的实际 PID。它通常用于:在宿主侧获取容器 init 进程或容器内子进程的 PID,以便与系统监控、日志或外部工具联动;配合WslcGetProcessState、WslcGetProcessExitCode、WslcGetProcessExitEvent构建完整的进程生命周期监控逻辑;验证进程是否已成功启动启动成功后 PID 应为非零值。需要说明的是,PID 的数值语义是Linux 侧进程号,与 Windows 侧进程 ID 无关;该值由 WSLC 运行时在容器内维护,宿主程序只负责读取。二、函数签名与参数详解WslcGetProcessPid的完整声明定义在 SDK 头文件 wslcsdk.h 中,并与 wslcgetprocesspid.md 文档保持一致:STDAPI WslcGetProcessPid(_In_ WslcProcess process, _Out_ uint32_t* pid);其中STDAPI是 COM/Win32 中HRESULT __stdcall的宏展开,表示该函数返回HRESULT并使用__stdcall调用约定。参数语义如下表所示:参数类型方向说明processWslcProcessin要查询的进程句柄,必须是由WslcCreateContainerProcess创建、或由WslcGetContainerInitProcess取得的有效句柄piduint32_t*out输出参数,调用成功后写入进程在容器内的 PID;调用失败时被初始化为0其中:_In_表示process为输入参数,函数不会修改其值;_Out_表示pid为输出参数,函数会向该指针指向的内存写入结果,调用方必须保证其指向有效的可写内存;WslcProcess是不透明句柄opaque handle,在 handle-types.md 中通过DECLARE_HANDLE(WslcProcess)声明。调用方不能直接解引用它,只能将其在 WSLC API 之间传递,并在使用完毕后通过WslcReleaseProcess释放。示例文档原样:uint32_t pid 0; HRESULT hr WslcGetProcessPid(process, pid);三、返回值与错误码函数返回HRESULT,成功时为S_OK。结合 SDK 实现 与 单元测试 中的验证,该接口在以下场景会返回错误:返回值触发条件说明S_OK查询成功pid被写入有效的进程 PIDE_POINTERprocess为nullptr,或pid为nullptr空指针参数错误,测试中对两种情况均有断言HRESULT_FROM_WIN32(ERROR_INVALID_STATE)句柄内部对应的进程对象为空表示process句柄虽然非空,但其内部状态无效例如进程对象已被销毁或句柄未正确关联运行时对象底层传播的HRESULTWSLCProcess::GetPid内部失败例如E_POINTER等由底层调用返回的错误WSLC 模块还定义了一组业务错误码,详见 error-codes.md,例如WSLC_E_CONTAINER_NOT_RUNNING0x80040605、WSLC_E_VM_NOT_RUNNING0x80040610等。WslcGetProcessPid本身不直接返回这些业务错误码,但它们可能在容器/VM 未运行导致进程对象失效的间接场景中由上层流程触发。最佳实践:调用前将pid初始化为0如示例所示,这样即使调用失败,输出值也是可判定的;调用后先检查hr S_OK,再使用pid值。四、SDK 层实现剖析WslcGetProcessPid的 SDK 层实现位于 wslcsdk.cpp,完整代码如下:STDAPI WslcGetProcessPid(_In_ WslcProcess process, _Out_ uint32_t* pid) try { auto internalType CheckAndGetInternalType(process); RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType-process); RETURN_HR_IF_NULL(E_POINTER, pid); *pid 0; int runtimePid{}; RETURN_IF_FAILED(internalType-process-GetPid(runtimePid)); *pid static_castuint32_t(runtimePid); return S_OK; } CATCH_RETURN();逐行解读:CheckAndGetInternalType(process):将外部的不透明句柄WslcProcess转换为 SDK 内部的类型对象,同时完成句柄合法性校验;RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType-process):若内部进程对象为空,返回无效状态错误——这对应句柄有效但运行时对象缺失的情况;RETURN_HR_IF_NULL(E_POINTER, pid):输出指针为空时直接返回E_POINTER;*pid 0:先清零输出值,保证失败路径下输出可判定;internalType-process-GetPid(runtimePid):调用底层WSLCProcess对象的GetPid方法获取运行时 PID类型为int;*pid static_castuint32_t(runtimePid):将底层int类型的 PID 转换为接口约定的uint32_t并写出;CATCH_RETURN():整个函数体包裹在 try/catch 宏中,将 C 异常统一转换为HRESULT,这是该 SDK 所有 API 的统一错误处理模式。从实现可以看到,接口对空句柄与内部对象无效两种错误做了区分:前者返回E_POINTER,后者返回ERROR_INVALID_STATE,这与测试中的断言一一对应。五、底层调用链:从 SDK 到 WSLCProcessSDK 层调用的GetPid属于wslcsession模块中的WSLCProcess类,实现在 WSLCProcess.cpp:HRESULT WSLCProcess::GetPid(int* Pid) try { RETURN_HR_IF_NULL(E_POINTER, Pid); *Pid m_control-GetPid(); return S_OK; } CATCH_RETURN(); int WSLCProcess::GetPid() const { return m_control-GetPid(); }可以看到两层调用结构:HRESULT WSLCProcess::GetPid(int*):带错误返回的版本,供 SDK 层调用,同样先做空指针检查;int WSLCProcess::GetPid() const:内联便捷重载,直接返回 PID 值。两版最终都委托给m_control-GetPid()。从源码结构可以推断,m_control是WSLCProcessControl类型的进程控制对象,负责维护进程在容器内的实际运行状态与 PID 信息——即 PID 的真实来源是进程控制层,SDK 与WSLCProcess只做取值与类型转换。整个调用链可概括为:WslcGetProcessPid (SDK 层, wslcsdk.cpp) └─ WSLCProcess::GetPid (wslcsession 层, WSLCProcess.cpp) └─ WSLCProcessControl::GetPid (进程控制对象)值得注意的是类型转换方向:底层 PID 以int存储与传递,接口层以uint32_t对外暴露。Linux PID 为非负值,因此转换是安全的,但调用方应当意识到接口输出是无符号 32 位整数这一约定。六、WinRT 投影:Process.Pid 属性WSLC 在 winrt 目录下提供了 WinRT 投影层,将 C API 包装为面向 WinRT 组件消费者的对象模型。在 Process.cpp 中,WslcGetProcessPid被投影为Process对象的Pid()属性:uint32_t Process::Pid() { uint32_t pid; winrt::check_hresult(WslcGetProcessPid(ToHandle(), pid)); return pid; }ToHandle()将 WinRT 对象内部持有的句柄还原为 C API 所需的WslcProcess;winrt::check_hresult负责将失败时的HRESULT转换为 WinRT 异常抛出,因此 C#/C/WinRT 等消费者无需逐次检查返回值,失败时直接通过异常感知。同一文件中还投影了State()对应WslcGetProcessState、ExitCode()对应WslcGetProcessExitCode、Signal()对应WslcSignalProcess等属性与方法,共同构成进程对象的完整 WinRT 面,详见 winrt/Process.cpp。七、测试验证:正确路径与错误路径单元测试 WslcSdkTests.cpp 中的ProcessGetPid测试方法完整覆盖了该 API 的正确与错误路径,其流程如下:WSLC_TEST_METHOD(ProcessGetPid) { // 1. 配置进程:容器内执行 /bin/sleep 99 WslcProcessSettings procSettings; VERIFY_SUCCEEDED(WslcInitProcessSettings(procSettings)); const char* argv[] {/bin/sleep, 99}; VERIFY_SUCCEEDED(WslcSetProcessSettingsCmdLine(procSettings, argv, ARRAYSIZE(argv))); // 2. 配置容器:以 debian:latest 为基础,将该进程设为 init 进程 WslcContainerSettings containerSettings; VERIFY_SUCCEEDED(WslcInitContainerSettings(debian:latest, containerSettings)); VERIFY_SUCCEEDED(WslcSetContainerSettingsInitProcess(containerSettings, procSettings)); // 3. 创建并启动容器 UniqueContainer container; VERIFY_SUCCEEDED(WslcCreateContainer(m_defaultSession, containerSettings, container, nullptr)); VERIFY_SUCCEEDED(WslcStartContainer(container.get(), WSLC_CONTAINER_START_FLAG_NONE, nullptr)); // 4. 取得 init 进程句柄 UniqueProcess process; VERIFY_SUCCEEDED(WslcGetContainerInitProcess(container.get(), process)); // 5. 正向断言:运行中进程的 PID 必须为非零 uint32_t pid 0; VERIFY_SUCCEEDED(WslcGetProcessPid(process.get(), pid)); VERIFY_IS_TRUE(pid 0); // 6. 负向断言:null pid 指针必须失败 VERIFY_ARE_EQUAL(WslcGetProcessPid(process.get(), nullptr), E_POINTER); // 7. 负向断言:null 进程句柄必须失败 WslcProcess nullProcess nullptr; VERIFY_ARE_EQUAL(WslcGetProcessPid(nullProcess, pid), E_POINTER); }测试要点:正向验证只断言pid 0,而非某个固定值——这符合 PID 由运行时动态分配、宿主程序不应假设具体数值的接口契约;两条负向路径分别验证pid nullptr与process nullptr均返回E_POINTER,与 SDK 实现 中两次RETURN_HR_IF_NULL(E_POINTER, ...)严格对应;整个测试依赖一套完整的容器生命周期WslcInitContainerSettings→WslcCreateContainer→WslcStartContainer→WslcGetContainerInitProcess,说明WslcGetProcessPid是进程启动后才能使用的查询接口。八、完整使用示例:宿主程序中查询容器进程 PID将测试流程泛化为宿主程序的完整调用序列,即可得到WslcGetProcessPid的端到端用法容器与会话相关 API 的完整组合可参考 end-to-end-example.md:#include windows.h #include wslcsdk.h HRESULT QueryContainerInitProcessPid(WslcSession session) { // 1. 配置进程:以 /bin/sleep 99 作为容器 init 进程 WslcProcessSettings procSettings; HRESULT hr WslcInitProcessSettings(procSettings); if (FAILED(hr)) return hr; const char* argv[] {/bin/sleep, 99}; hr WslcSetProcessSettingsCmdLine(procSettings, argv, ARRAYSIZE(argv)); if (FAILED(hr)) return hr; // 2. 配置容器并挂载 init 进程 WslcContainerSettings containerSettings; hr WslcInitContainerSettings(debian:latest, containerSettings); if (FAILED(hr)) return hr; hr WslcSetContainerSettingsInitProcess(containerSettings, procSettings); if (FAILED(hr)) return hr; // 3. 创建并启动容器 WslcContainer container nullptr; hr WslcCreateContainer(session, containerSettings, container, nullptr); if (FAILED(hr)) return hr; hr WslcStartContainer(container, WSLC_CONTAINER_START_FLAG_NONE, nullptr); if (FAILED(hr)) return hr; // 4. 获取 init 进程句柄 WslcProcess process nullptr; hr WslcGetContainerInitProcess(container, process); if (FAILED(hr)) return hr; // 5. 查询 PID:先清零,成功后才使用 uint32_t pid 0; hr WslcGetProcessPid(process, pid); if (SUCCEEDED(hr) pid 0) { // pid 即为容器内 init 进程的 Linux PID } // 6. 释放资源 WslcReleaseProcess(process); WslcReleaseContainer(container); return hr; }使用要点:WslcGetProcessPid只读不阻塞:它是纯查询接口,不会等待进程退出,也不会触发任何 I/O,适合在监控循环或状态上报逻辑中高频调用;先清零后校验:将pid初始化为0并仅在接受S_OK后使用,避免读取未初始化的输出值;与兄弟接口配合:需要判断进程是否仍在运行时,优先使用WslcGetProcessState返回WslcProcessState枚举,见 wslcgetprocessstate.md;需要等待退出时可结合WslcGetProcessExitEventwslcgetprocessexitevent.md;进程退出后可通过 wslcgetprocessexitcode.md 获取退出码——三者与WslcGetProcessPid共同构成完整的进程生命周期查询面。九、相关 API 与进一步阅读同组进程查询接口均位于 process-apis:WslcGetProcessState:查询进程状态Unknown / Running / Exited / SignalledWslcGetProcessExitCode:查询进程退出码WslcGetProcessExitEvent:获取进程退出事件句柄,用于WaitForSingleObject等待WslcSignalProcess:向进程发送信号如WSLC_SIGNAL_SIGKILLWslcGetProcessIOHandle:获取进程标准 I/O 句柄WslcReleaseProcess:释放进程句柄上游关联接口:WslcCreateContainerProcess:在容器内创建新进程WslcGetContainerInitProcess:获取容器 init 进程句柄测试中获取 PID 的标准入口WslcCreateSession 与 会话 API:提供容器运行所需的会话上下文参考材料:接口声明与文档:wslcsdk.h、wslcgetprocesspid.mdSDK 实现:wslcsdk.cpp底层实现:WSLCProcess.cppWinRT 投影:winrt/Process.cpp测试用例:WslcSdkTests.cpp句柄类型定义:handle-types.md错误码表:error-codes.md【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价