程運(yùn)行狀態(tài))
WSL 容器 SDK C 接口 WslcGetProcessState 詳解查詢 WSL 容器進(jìn)程運(yùn)行狀態(tài)【免費(fèi)下載鏈接】WSLWindows Subsystem for Linux項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ws/WSLWslcGetProcessState是 WSL Container SDKWSLC SDK中用于查詢?nèi)萜鲀?nèi) Linux 進(jìn)程運(yùn)行狀態(tài)的核心 C API調(diào)用方通過一個(gè)WslcProcess句柄即可獲取進(jìn)程當(dāng)前所處的狀態(tài)運(yùn)行中、已退出、被信號終止或未知。本文將結(jié)合該 API 在 wslcsdk.h 中的聲明、wslcsdk.cpp 中的實(shí)現(xiàn)以及 WslcSdkTests.cpp 中的測試用例深入講解其簽名、狀態(tài)枚舉語義、底層實(shí)現(xiàn)原理與實(shí)戰(zhàn)用法幫助開發(fā)者在 WSL 容器生命周期管理中正確地進(jìn)行進(jìn)程狀態(tài)輪詢與退出判定。函數(shù)簽名WslcGetProcessState的原型定義如下見 wslcsdk.hSTDAPI WslcGetProcessState(_In_ WslcProcess process, _Out_ WslcProcessState* state);參數(shù)類型方向說明processWslcProcessin有效的 WSL 容器進(jìn)程句柄通常由WslcCreateContainerProcess或WslcGetContainerInitProcess返回stateWslcProcessState*out輸出參數(shù)接收進(jìn)程當(dāng)前狀態(tài)該枚舉在 wslcprocessstate.md 中有完整定義返回值HRESULTS_OK表示查詢成功失敗時(shí)返回對應(yīng)的錯(cuò)誤碼詳見下文返回值與錯(cuò)誤處理。該函數(shù)已通過 wslcsdk.def 導(dǎo)出為 SDK 公共符號屬于 WSLC SDK 的進(jìn)程管理PROCESS MANAGEMENT接口組與之并列的還包括WslcGetProcessPid、WslcGetProcessExitEvent、WslcGetProcessExitCode、WslcSignalProcess、WslcGetProcessIOHandle與WslcReleaseProcess完整清單見 Process APIs 索引。WslcProcessState 狀態(tài)枚舉語義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;枚舉值數(shù)值語義WSLC_PROCESS_STATE_UNKNOWN0狀態(tài)未知。SDK 實(shí)現(xiàn)會將輸出初始化為該值僅在調(diào)用成功但無法獲得明確狀態(tài)時(shí)出現(xiàn)WSLC_PROCESS_STATE_RUNNING1進(jìn)程正在運(yùn)行尚未觸發(fā)退出事件WSLC_PROCESS_STATE_EXITED2進(jìn)程已正常退出可通過WslcGetProcessExitCode獲取退出碼WSLC_PROCESS_STATE_SIGNALLED3進(jìn)程被信號如SIGKILL、SIGTERM終止值得注意的一點(diǎn)SDK 公共頭文件中的該枚舉與 WSL 服務(wù)內(nèi)部 IDL 定義的WSLCProcessState見 WSLCShared.idl在數(shù)值上嚴(yán)格一致。實(shí)現(xiàn)中通過static_assert強(qiáng)制保證兩者恒等見 wslcsdk.cpp確保公共 API 層與內(nèi)部服務(wù)層的狀態(tài)值可以安全互轉(zhuǎn)。返回值與錯(cuò)誤處理WslcGetProcessState返回HRESULT可能的值包括S_OK查詢成功state被寫入有效狀態(tài)值E_POINTER傳入的state為nullptr或process句柄為nullptrHRESULT_FROM_WIN32(ERROR_INVALID_STATE)process句柄有效但內(nèi)部進(jìn)程對象已被釋放internalType-process為空即句柄處于懸空狀態(tài)。從實(shí)現(xiàn)代碼wslcsdk.cpp可以看到嚴(yán)格的三段式校驗(yàn)流程STDAPI WslcGetProcessState(_In_ WslcProcess process, _Out_ WslcProcessState* state) try { static_assert(/* 公共枚舉與服務(wù)內(nèi)部枚舉數(shù)值一致 */); 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句柄轉(zhuǎn)換為內(nèi)部類型WslcProcessImpl其核心成員是wil::com_ptrIWSLCCompatProcess process見 WslcsdkPrivate.h真正的狀態(tài)查詢最終委托給 COM 對象IWSLCCompatProcess::GetState。句柄的重新解釋轉(zhuǎn)換定義在 WslcsdkPrivate.cpp。底層實(shí)現(xiàn)原理退出事件驅(qū)動(dòng)的狀態(tài)判定WslcGetProcessState并不向容器內(nèi)發(fā)送任何探測消息而是由 WSL 服務(wù)側(cè)的進(jìn)程控制對象根據(jù)退出事件是否已被觸發(fā)來判定狀態(tài)。核心邏輯位于 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}; } }解讀這段實(shí)現(xiàn)可以得到兩個(gè)關(guān)鍵事實(shí)狀態(tài)由m_exitEvent決定m_exitEvent是一個(gè)wil::unique_event采用手動(dòng)復(fù)位ManualReset模式見 WSLCProcessControl.h。退出事件未觸發(fā) → 判定為RUNNING退出事件已觸發(fā) → 判定為EXITED。退出碼與狀態(tài)同步維護(hù)m_exitedCode是std::optionalint進(jìn)程退出碼通過SetExitCode記錄僅記錄首個(gè)退出碼后續(xù)寫入被忽略并由SignalExit觸發(fā)退出事件。對于容器被直接釋放如--rm容器在銷毀事件中才補(bǔ)發(fā) init 退出信號或仍在運(yùn)行即被強(qiáng)制拆除的場景WSLCProcessControl會合成128 SIGKILL作為退出碼見 WSLCProcessControl.cpp。此外同一底層狀態(tài)的消費(fèi)方不止WslcGetProcessState一處。比如RunningWSLCProcess::GetExitCode見 WSLCProcessLauncher.cpp會先查詢狀態(tài)只有狀態(tài)為EXITED或SIGNALLED時(shí)才返回退出碼否則拋出ERROR_INVALID_STATE——這與WslcGetProcessExitCode的行為保持一致見下文。與其他進(jìn)程管理 API 的組合使用WslcGetProcessState通常不單獨(dú)使用而是與以下 API 配合完成完整的進(jìn)程生命周期管理全部列于 Process APIs 索引API作用與狀態(tài)查詢的關(guān)系WslcGetProcessExitEvent獲取進(jìn)程退出事件句柄HANDLE見 wslcgetprocessexitevent.md比輪詢更高效用WaitForSingleObject等待事件避免忙等WslcGetProcessExitCode獲取進(jìn)程退出碼見 wslcgetprocessexitcode.md僅當(dāng)狀態(tài)為EXITED/SIGNALLED時(shí)調(diào)用才返回S_OKWslcSignalProcess向進(jìn)程發(fā)送信號SIGHUP/SIGINT/SIGQUIT/SIGKILL/SIGTERM見 wslcsignalprocess.md發(fā)送信號后可調(diào)用本函數(shù)確認(rèn)進(jìn)程狀態(tài)遷移WslcGetProcessPid獲取容器內(nèi)進(jìn)程 PID狀態(tài)為RUNNING時(shí) PID 有效WslcReleaseProcess釋放進(jìn)程句柄釋放后句柄失效再調(diào)用本函數(shù)將返回ERROR_INVALID_STATE關(guān)于退出碼的一個(gè)重要約束WslcGetProcessExitCodewslcsdk.cpp在進(jìn)程仍在運(yùn)行時(shí)會返回HRESULT_FROM_WIN32(ERROR_INVALID_STATE)同時(shí)把退出碼輸出初始化為-1。因此典型判程范式是先調(diào)用WslcGetProcessState確認(rèn)狀態(tài)已離開RUNNING再讀取退出碼避免拿到無意義的中間值。完整實(shí)戰(zhàn)示例輪詢等待進(jìn)程退出以下示例完整演示了從創(chuàng)建進(jìn)程、輪詢狀態(tài)到讀取退出碼的完整流程可在遵循 SDK 初始化的前提下直接套用#include windows.h #include wslcsdk.h HRESULT WaitForProcessAndGetExitCode(WslcProcess process, INT32* finalExitCode) { // 1. 初始化輸出 *finalExitCode -1; // 2. 輪詢進(jìn)程狀態(tài)直到離開 RUNNING for (;;) { WslcProcessState state WSLC_PROCESS_STATE_UNKNOWN; HRESULT hr WslcGetProcessState(process, state); if (FAILED(hr)) { return hr; } if (state WSLC_PROCESS_STATE_RUNNING) { // 進(jìn)程仍在運(yùn)行短暫休眠后重試 Sleep(100); continue; } // 3. 狀態(tài)已變?yōu)?EXITED 或 SIGNALLED讀取退出碼 INT32 exitCode 0; hr WslcGetProcessExitCode(process, exitCode); if (FAILED(hr)) { // 仍可能因競態(tài)返回 ERROR_INVALID_STATE可重試或記錄狀態(tài) return hr; } *finalExitCode exitCode; return S_OK; } }更推薦的做法是用WslcGetProcessExitEvent獲取退出事件句柄并阻塞等待從根本上消除輪詢開銷WslcProcessState state WSLC_PROCESS_STATE_UNKNOWN; HRESULT hr WslcGetProcessState(process, state); // 文檔示例中的最小調(diào)用形式上面的最小調(diào)用形式初始化state為WSLC_PROCESS_STATE_UNKNOWN后傳入也正是 wslcgetprocessstate.md 官方文檔給出的示例寫法。測試用例驗(yàn)證的行為約定SDK 自帶的集成測試 WslcSdkTests.cpp 的ProcessGetState用例完整驗(yàn)證了本 API 的關(guān)鍵行為是理解語義最直接的參考WSLC_TEST_METHOD(ProcessGetState) { // 準(zhǔn)備在 debian:latest 容器中啟動(dòng) /bin/sleep 99 作為 init 進(jìn)程 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)); // 運(yùn)行中狀態(tài)為 RUNNING退出碼讀取應(yīng)失敗 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 后等待退出事件狀態(tài)應(yīng)為 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); // 負(fù)向用例null 輸出指針 / null 進(jìn)程句柄均返回 E_POINTER VERIFY_ARE_EQUAL(WslcGetProcessState(process.get(), nullptr), E_POINTER); WslcProcess nullProcess nullptr; WslcProcessState state3{}; VERIFY_ARE_EQUAL(WslcGetProcessState(nullProcess, state3), E_POINTER); }該用例驗(yàn)證了四個(gè)約定運(yùn)行中狀態(tài)容器啟動(dòng)后、進(jìn)程存活期間WslcGetProcessState返回WSLC_PROCESS_STATE_RUNNING退出碼語義運(yùn)行中調(diào)用WslcGetProcessExitCode返回ERROR_INVALID_STATE且退出碼被置為-1佐證了先查狀態(tài)、再取退出碼的調(diào)用順序信號終止后的狀態(tài)SIGKILL后等待退出事件被觸發(fā)狀態(tài)變?yōu)镾IGNALLED或EXITED二者之一——這是因?yàn)榉?wù)側(cè)對被信號終止與已退出的最終呈現(xiàn)存在容器運(yùn)行時(shí)的差異調(diào)用方應(yīng)同時(shí)接受這兩種狀態(tài)參數(shù)校驗(yàn)state為nullptr、process為nullptr時(shí)均返回E_POINTER與實(shí)現(xiàn)中的校驗(yàn)邏輯吻合。WinRT 與高級語言封裝對于使用 WinRT/C# 的開發(fā)場景SDK 在 Process.cpp 中提供了Process::State()封裝內(nèi)部直接調(diào)用本函數(shù)并做 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會先校驗(yàn)進(jìn)程已啟動(dòng)未啟動(dòng)時(shí)拋出hresult_illegal_method_call這與 C API 層進(jìn)程對象缺失返回ERROR_INVALID_STATE的錯(cuò)誤語義一脈相承。注意事項(xiàng)與最佳實(shí)踐不要在退出事件已觸發(fā)后繼續(xù)持有進(jìn)程句柄WslcReleaseProcess釋放后任何WslcGetProcessState調(diào)用都會返回ERROR_INVALID_STATE因此狀態(tài)查詢應(yīng)放在釋放句柄之前完成。狀態(tài)輪詢要有退避如需輪詢建議結(jié)合WslcGetProcessExitEvent使用事件等待如測試中的WaitForSingleObject(exitEvent, 30 * 1000)而不是高頻忙等以降低對 WSL 服務(wù)側(cè)進(jìn)程控制對象的壓力。區(qū)分EXITED與SIGNALLED被信號終止的進(jìn)程最終狀態(tài)可能是兩者之一業(yè)務(wù)邏輯應(yīng)把二者統(tǒng)一視為進(jìn)程已終止并配合退出碼如128 signal慣例判斷終止原因。先初始化輸出調(diào)用前將state初始化為WSLC_PROCESS_STATE_UNKNOWN官方示例即如此即使調(diào)用失敗也不會讀到未定義值——SDK 內(nèi)部同樣會在寫入前先做初始化雙重保險(xiǎn)。預(yù)覽版 API 的穩(wěn)定性聲明WSLC SDK 頭文件wslcsdk.h明確標(biāo)注該 API 處于預(yù)覽階段簽名與行為可能在不預(yù)先通知的情況下變更請勿將其作為生產(chǎn)環(huán)境的關(guān)鍵依賴。參考鏈接API 文檔WslcGetProcessStateAPI 文檔WslcProcessState 枚舉Process APIs 完整索引SDK 公共頭文件 wslcsdk.hSDK 實(shí)現(xiàn) wslcsdk.cpp服務(wù)側(cè)進(jìn)程控制 WSLCProcessControl.cpp內(nèi)部狀態(tài)枚舉 WSLCShared.idl集成測試 WslcSdkTests.cpp【免費(fèi)下載鏈接】WSLWindows Subsystem for Linux項(xiàng)目地址: https://gitcode.com/GitHub_Trending/ws/WSL創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考