WSL WslcLoadSessionImage C API 指南:从 HANDLE 加载容器镜像到 WSL 会话
发布时间:2026/9/10 23:36:27来源:尧图网络
WSL WslcLoadSessionImage C API 指南从 HANDLE 加载容器镜像到 WSL 会话【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSLWslcLoadSessionImage 是 Windows Subsystem for LinuxWSLC 容器 SDKWslcSDK中负责将已保存的容器镜像tar 归档加载进 WSL 会话的核心 API。本文以 wslcloadsessionimage.md 为骨架结合仓库源码wslcsdk.cpp、wslcsdk.h与测试用例完整讲解其函数签名、参数语义、底层调用链、校验规则与实战用法帮助读者在 C/C 程序中可靠地完成镜像加载。WslcLoadSessionImage 是什么WslcLoadSessionImage 是 WSL 容器 C APIWslcSDK导出符号见 wslcsdk.def中一组镜像管理函数之一属于 Image APIs 家族。它的作用是把一份已经导出的容器镜像 tar 文件加载到指定的WslcSession会话中加载成功后该镜像即可用于创建并运行容器。镜像生命周期中的相关 API 还包括拉取WslcPullSessionImage、导入WslcImportSessionImage/WslcImportSessionImageFromFile、删除WslcDeleteSessionImage、列举WslcListSessionImages、打标签WslcTagSessionImage与推送WslcPushSessionImage。其中Import 与 Load 的区别导入时调用方需额外提供镜像名称将数据与名称绑定写入镜像库而 Load 直接加载已保存的镜像归档镜像原有的名称与标签随归档一并恢复。从源码结构看Load 更贴近docker load的语义Import 更贴近docker import。函数签名与参数详解原文档给出的完整声明头文件声明位于 wslcsdk.hSTDAPI WslcLoadSessionImage( _In_ WslcSession session, _In_ HANDLE imageContent, _In_ uint64_t imageContentBytes, _In_opt_ const WslcLoadImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage);参数类型方向说明sessionWslcSessionin目标 WSL 会话句柄必须是由WslcCreateSession创建且尚未释放的有效会话imageContentHANDLEin指向镜像内容tar 文件的打开句柄需具有 GENERIC_READ 权限imageContentBytesuint64_tin镜像内容的字节数必须大于 0optionsconst WslcLoadImageOptions*in, optional可选配置进度回调等可传NULLerrorMessagePWSTR*out, optional失败时接收动态分配的本地化错误信息可传NULL返回值HRESULT。成功返回S_OK失败时可通过errorMessage获取可读的错误描述由调用方用CoTaskMemFree释放。关键提示imageContent 是 HANDLE 而非 void*原文档特别强调头文件将imageContent声明为HANDLE而不是void*。这意味着调用方不能直接把任意内存指针传入而必须先通过CreateFileW、CreateFile2等 API 打开镜像文件取得内核句柄或传入任意合法的文件/流句柄。这一设计使 SDK 能够在内核层面对镜像内容进行统一的句柄包装与长度校验也方便将同一加载流程复用于来自管道、内存映射或其他来源的文件句柄。基础用法完整可运行的加载示例原文档示例展示了最典型的使用路径——打开磁盘上的 tar 文件、获取大小、调用 API、关闭句柄。下面结合参数校验要求做完整保留并补充错误处理#include windows.h #include wslcsdk.h // WslcSession 及本 API 的声明 HRESULT LoadImageFromFile(WslcSession session, const wchar_t* imagePath) { // 1. 以只读、允许共享读取的方式打开镜像 tar 文件 HANDLE imageContent CreateFileW( imagePath, // 例如 LC:\\images\\demo-load.tar GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (imageContent INVALID_HANDLE_VALUE) { return HRESULT_FROM_WIN32(GetLastError()); } // 2. 查询文件大小64 位作为 imageContentBytes 传入 LARGE_INTEGER size { 0 }; BOOL ok GetFileSizeEx(imageContent, size); if (!ok) { CloseHandle(imageContent); return HRESULT_FROM_WIN32(GetLastError()); } // 3. 可选配置此处传空结构等同于使用默认行为 WslcLoadImageOptions loadOptions { 0 }; // 4. 执行加载errorMessage 可传 NULL 表示不关心错误文本 HRESULT hr WslcLoadSessionImage( session, imageContent, (uint64_t)size.QuadPart, loadOptions, NULL); // 5. 句柄由调用方负责关闭 CloseHandle(imageContent); return hr; }要点imageContentBytes必须与句柄指向的实际内容长度一致。从源码看该值会被原样传给底层加载逻辑用于界定数据范围传入错误长度会导致解析失败。句柄的所有权始终归调用方SDK 内部不会关闭imageContent调用结束后需自行CloseHandle。若传入NULL作为optionsSDK 内部会跳过进度回调的创建见下文实现分析行为等价于加载时不报告进度。WslcLoadImageOptions进度回调节点WslcLoadImageOptions的结构定义在 wslcsdk.h并有独立参考文档 wslcloadimageoptions.mdtypedef struct WslcLoadImageOptions { _In_opt_ WslcContainerImageProgressCallback progressCallback; _In_opt_ PVOID progressCallbackContext; } WslcLoadImageOptions;字段类型说明progressCallbackWslcContainerImageProgressCallback加载过程中回调的函数指针可为 NULLprogressCallbackContextPVOID透传给回调的用户上下文指针可为 NULL回调类型定义wslcsdk.htypedef HRESULT(CALLBACK* WslcContainerImageProgressCallback)( const WslcImageProgressMessage* progress, PVOID context);进度消息WslcImageProgressMessagewslcsdk.h包含三个字段id层 ID 或摘要、status如下载、解压等阶段与detail进度细节。对长时间运行的加载任务建议通过回调向 UI 或日志汇报进度避免用户误以为程序无响应。底层实现从 HANDLE 到会话的调用链在 wslcsdk.cpp 中WslcLoadSessionImage的公共入口只做三件事包装错误信息、解析会话内部对象、把参数交给静态实现函数static HRESULT WslcLoadSessionImageImpl( WslcSessionImpl* internalSession, const WslcLoadImageOptions* options, ErrorInfoWrapper errorInfoWrapper, const ImageFileResolver imageFile) { auto progressCallback ProgressCallback::CreateIf(options); return errorInfoWrapper.CaptureResult(internalSession-session-LoadImage( wsl::windows::common::apicompat::Convert(ToCOMInputHandle(imageFile.Handle())), progressCallback.get(), imageFile.Length(), nullptr)); } STDAPI WslcLoadSessionImage( _In_ WslcSession session, _In_ HANDLE imageContent, _In_ uint64_t imageContentLength, _In_opt_ const WslcLoadImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage) try { ErrorInfoWrapper errorInfoWrapper{errorMessage}; auto internalType CheckAndGetInternalType(session); RETURN_HR_IF_NULL(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), internalType-session); return WslcLoadSessionImageImpl(internalType, options, errorInfoWrapper, {imageContent, imageContentLength}); } CATCH_RETURN();从中可以提炼出三条实现事实会话校验前置进入实现前先执行CheckAndGetInternalType(session)若会话内部对象为空返回HRESULT_FROM_WIN32(ERROR_INVALID_STATE)即调用无效会话会以失败状态告终而不是崩溃。输入归一化ImageFileResolverwslcsdk.cpp是所有镜像文件输入的公共适配层。基于 HANDLE长度的构造器会执行硬性校验imageContent nullptr或 INVALID_HANDLE_VALUE时抛出E_INVALIDARGimageContentLength 0时同样抛出E_INVALIDARG。这与测试用例中的负例断言完全一致。委托给会话引擎最终调用internalSession-session-LoadImage(...)传入转换后的 COM 输入句柄、进度回调与内容长度由 WSL 运行时负责实际的镜像解析与装载。兄弟 APIWslcLoadSessionImageFromFile若调用方手中只有文件路径而没有句柄可选用同族的 WslcLoadSessionImageFromFileSTDAPI WslcLoadSessionImageFromFile( _In_ WslcSession session, _In_z_ PCWSTR path, _In_opt_ const WslcLoadImageOptions* options, _Outptr_opt_result_z_ PWSTR* errorMessage);其实现wslcsdk.cpp与WslcLoadSessionImage共用同一个WslcLoadSessionImageImpl区别仅在于输入ImageFileResolver的路径构造器wslcsdk.cpp内部完成CreateFileW(GENERIC_READ | FILE_SHARE_READ | OPEN_EXISTING)打开文件并查询GetFileSizeEx长度path为NULL时抛出E_POINTER。因此两者加载行为完全一致选择依据是调用方手上是句柄长度还是路径路径变体内部会打开并自动管理文件句柄调用方无需也不应自行关闭其内部句柄。这也解释了 WSL 容器 WinRT 投影层Session.cpp为何在LoadImage/LoadImageAsync中直接使用WslcLoadSessionImageFromFile——路径形式对上层封装更友好且能配合IAsyncActionWithProgress汇报进度。错误处理与失败场景根据 WslcSdkTests.cpp 中LoadImage测试方法的正负例可确认以下行为契约输入预期结果合法文件句柄 正确长度S_OK随后可用该镜像运行容器imageContent为NULLE_INVALIDARGimageContent为INVALID_HANDLE_VALUEE_INVALIDARGimageContentBytes为 0E_INVALIDARGFromFile 变体path为NULLE_POINTER测试还验证了端到端场景先WslcDeleteSessionImage清理同名镜像再通过本 API 加载hello-world:latest的 tar 归档随后运行容器并断言输出包含Hello from Docker!——证明 Load 成功后镜像立即可执行。负例均通过VERIFY_ARE_EQUAL(..., E_INVALIDARG / E_POINTER)断言说明输入校验由 SDK 层强保证不依赖底层运行时兜底。实践中建议遵循如下错误处理模式PWSTR errorMessage nullptr; HRESULT hr WslcLoadSessionImage(session, imageContent, bytes, options, errorMessage); if (FAILED(hr)) { if (errorMessage) { // 输出/记录 errorMessage注意 UTF-16使用后释放 CoTaskMemFree(errorMessage); } // 根据 hr 分别处理 E_INVALIDARG、ERROR_INVALID_STATE 等 }其中errorMessage由 SDK 通过CoTaskMemAlloc分配调用方负责CoTaskMemFree不需要错误文本时直接传NULL即可。使用前提与注意事项会话前提session必须是有效且处于已启动状态的WslcSession参考 wslcsdk.h 的WslcCreateSession。加载前建议通过WslcCreateContainer流程确认会话可用。镜像格式本 API 面向已导出的容器镜像 tar 归档。从测试中的LoadImageNonTar用例当前标记SKIP_TEST_NOT_IMPL见 WslcSdkTests.cpp看非 tar 输入的处理尚未完全覆盖应避免传入非镜像文件。句柄语义传入的HANDLE不会被 SDK 关闭生命周期归调用方FILE_SHARE_READ共享模式可避免与其他读取方冲突。C#/WinRT 投影差异C# 与 WinRT 元数据层仅暴露基于路径的LoadImage/LoadImageAsync原始 HANDLE 重载不投影见 known-gaps.md 与 not-yet-implemented-and-known-gaps.md。因此 HANDLE 形式的WslcLoadSessionImage是 C/C 调用方的专属能力适合需要从内存映射、网络流等非文件来源加载镜像的场景。小结WslcLoadSessionImage 提供了一条明确的镜像加载路径调用方持有只读句柄 精确字节数SDK 校验输入合法性后交由会话运行时完成加载并以HRESULT与可选错误文本返回结果。理解其参数语义尤其是 HANDLE 而非指针、WslcLoadImageOptions进度回调以及WslcLoadSessionImageFromFile这一路径变体即可在 WSL 容器 C 应用中稳定地实现docker load等价功能。进一步可参考 Image APIs 总览 了解镜像拉取、导入、删除、列举等配套 API或阅读 WslcSdkTests.cpp 中的完整测试场景。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网