☰
WSL 容器 SDK(WSLC)C API 深入解析:WslcInitSessionSettings 会话初始化
2026/10/11 5:14:51 网站建设 项目流程

WSL 容器 SDK(WSLC)C API 深入解析:WslcInitSessionSettings 会话初始化

【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL

本篇文章以 Windows Subsystem for Linux(WSL)容器 SDK(WSLC)C API 中的WslcInitSessionSettings函数为核心,系统讲解 WSLC 会话(Session)的初始化流程、参数语义、默认值与底层实现原理。你将掌握如何通过该 API 声明会话名称与存储路径、理解会话名称作为机器级键的约束与安全边界,并学会在真实代码(含官方 HelloWorld 示例与 SDK 测试用例)中正确使用该函数开启一个 WSL 容器会话的生命周期。

WslcInitSessionSettings 在 WSLC 会话模型中的位置

WSLC(WSL Container)SDK 允许 Windows 应用程序以编程方式创建、配置、启动和终止轻量级 WSL 容器与其中的 Linux 进程。整个模型以“会话(Session)”为顶层单元:会话是一组容器、进程与资源的承载边界,也是 SDK 各项操作(拉取镜像、创建容器、运行进程)的上下文。

WslcInitSessionSettings正是会话生命周期的第一个函数调用:它负责把调用者提供的会话名称与存储路径写入一个WslcSessionSettings结构体,为后续的WslcCreateSession(真正创建会话)准备配置。从 src/windows/WslcSDK/wslcsdk.cpp 的实现可以看到,该函数本身并不启动任何后台服务,而是纯粹的“配置初始化”,随后由创建/设置类 API 消费这些配置。

在 C 语言 API 参考索引 中,会话相关 API 被集中收录于 Session APIs 页面,WslcInitSessionSettings是该 API 家族中第一个被调用的成员,其后才是WslcSetSessionSettingsCpuCount、WslcSetSessionSettingsMemory等可选配置项以及WslcCreateSession。

函数签名与参数详解

STDAPI WslcInitSessionSettings(_In_ PCWSTR name, _In_ PCWSTR storagePath, _Out_ WslcSessionSettings* sessionSettings);
参数类型方向说明
namePCWSTRin待创建会话的名称,同时充当显示名称。
storagePathPCWSTRin会话存储的写入路径;若路径不存在,会被自动创建。
sessionSettingsWslcSessionSettings*out指向用于接收设置结果的WslcSessionSettings结构的指针。

WslcSessionSettings是一个不透明结构体,其定义位于 src/windows/WslcSDK/wslcsdk.h:

#define WSLC_SESSION_OPTIONS_SIZE 72 #define WSLC_SESSION_OPTIONS_ALIGNMENT 8 typedef struct WslcSessionSettings { __declspec(align(WSLC_SESSION_OPTIONS_ALIGNMENT)) BYTE _opaque[WSLC_SESSION_OPTIONS_SIZE]; } WslcSessionSettings;

调用者无需也不应直接读写该结构内部字段,而应通过WslcInitSessionSettings完成初始化,再借助WslcSetSessionSettings*系列 API 调整具体配置。这种设计将内部布局(当前为 72 字节、8 字节对齐)与调用方解耦,便于 SDK 演进时维持 ABI 兼容。

返回值

函数返回HRESULT。成功时返回S_OK。从 wslcsdk.cpp 实现 可见,若name或storagePath为NULL,函数返回E_POINTER:

RETURN_HR_IF_NULL(E_POINTER, name); RETURN_HR_IF_NULL(E_POINTER, storagePath);

此外,根据 API 文档说明:如果已存在同名会话,则会话创建(而非初始化本身)将失败并返回ERROR_ALREADY_EXISTS。也就是说,名称冲突检查发生在后续的WslcCreateSession阶段。

会话名称:显示名、机器级键与安全边界

文档明确强调,会话名称承担双重职责:

  1. 显示名称:在日志、诊断信息与面向用户的管理界面中展示;
  2. 机器级键(machine-wide key):用于在整个机器范围内唯一标识一个会话。

正因为名称是机器级键,WslcInitSessionSettings允许不同用户创建的会话在命名上产生冲突,而冲突会在WslcCreateSession时以ERROR_ALREADY_EXISTS失败告终。因此,应用若需要为每个用户隔离会话,应在名称中显式编码用户维度(例如用户名或 SID 后缀),避免跨用户冲突。

全机器可见的会话元信息

即使会话本身属于某个用户,以下信息依然对机器上的所有用户可见:

  • 会话的名称(name);
  • 创建会话的用户的 SID;
  • 创建会话的进程 PID。

这意味着调用者不应将会话名称当作安全边界。文档给出的明确告诫是:

Do not put credentials or other sensitive information in the session's name.

(不要在会话名称中放置凭据或其他敏感信息。)

这是会话命名中必须遵守的安全红线:即使名称形如“机密项目_令牌ABC”便于区分,也会因其全机器可见性而构成信息泄露风险。应在名称中仅使用可公开的业务标识符,把敏感内容放入会话存储或配置文件中。

storagePath:会话存储的落地位置

storagePath指定会话存储的写入路径。文档说明:若该路径不存在,SDK 会自动创建。从测试用例 test/windows/WslcSdkTests.cpp 可以看到,测试框架使用工作目录下的test-storage子目录:

m_storagePath = std::filesystem::current_path() / "test-storage"; WslcSessionSettings sessionSettings; VERIFY_SUCCEEDED(WslcInitSessionSettings(c_testSessionName, m_storagePath.c_str(), &sessionSettings));

值得注意的实践细节:由于默认会话存储卷可达 32 GB(见下文默认值),且不同会话共享同一存储路径可显著减少镜像拉取开销,测试代码特意选择“与 WSLC 运行时测试共用同一存储路径”(见 WslcSdkTests.cpp 注释)。这为生产环境的应用提供了一个参考策略:在同一台机器上复用稳定的存储路径,可以复用已拉取的镜像与缓存,降低首次启动延迟与磁盘占用。

在实际开发中,建议:

  • 使用绝对路径(如C:\WSLC\<app-name>\session),避免依赖进程当前工作目录;
  • 为不同应用或不同环境规划独立的存储根目录,便于清理与迁移;
  • 注意磁盘空间规划——默认 VHD 容量上限为 32 GB(详见下文),需确保存储所在卷有足够余量。

源码级实现剖析:初始化到底做了什么

WslcInitSessionSettings 的实现 非常精简,展示了“配置初始化”的全部逻辑:

STDAPI WslcInitSessionSettings(_In_ PCWSTR name, _In_ PCWSTR storagePath, _Out_ WslcSessionSettings* sessionSettings) try { RETURN_HR_IF_NULL(E_POINTER, name); RETURN_HR_IF_NULL(E_POINTER, storagePath); auto internalType = CheckAndGetInternalType(sessionSettings); *internalType = {}; internalType->displayName = name; internalType->storagePath = storagePath; internalType->cpuCount = s_DefaultCPUCount; internalType->memoryMb = s_DefaultMemoryMB; internalType->timeoutMS = s_DefaultBootTimeout; internalType->vhdRequirements.sizeBytes = s_DefaultStorageSize; return S_OK; } CATCH_RETURN();

其核心行为可归纳为三点:

  1. 空指针防护:对name与storagePath做空指针检查,非法输入直接返回E_POINTER;
  2. 清空并写入基本配置:通过CheckAndGetInternalType取得内部类型后,先整体清零,再写入displayName与storagePath;
  3. 填充默认资源规格:CPU、内存、启动超时、存储容量全部被赋为 SDK 默认值。

默认值一览

默认值定义于 src/windows/WslcSDK/Defaults.h:

constexpr uint32_t s_DefaultCPUCount = 2; // 默认 2 个 CPU constexpr uint32_t s_DefaultMemoryMB = 2000; // 默认 2000 MB(约 2 GB)内存 // Maximum value per use with HVSOCKET_CONNECT_TIMEOUT_MAX constexpr ULONG s_DefaultBootTimeout = 300000; // 默认启动超时 300000 ms(5 分钟) // Default to 32 GB constexpr UINT64 s_DefaultStorageSize = 32ULL * 1024 * 1024 * 1024; // 默认存储 32 GB
配置项默认值说明
CPU 数2会话可见的 vCPU 数量
内存2000MB约 2 GB,单位为 MB
启动超时300000ms5 分钟,注释提示其上限受HVSOCKET_CONNECT_TIMEOUT_MAX约束
存储容量32GB会话存储 VHD 的默认容量上限

从实现可以看出,所有默认值在WslcInitSessionSettings阶段即被写入。这解释了为什么“初始化后立即调用WslcCreateSession”也能得到一个合理配置的会话;若需调整,再调用WslcSetSessionSettingsCpuCount、WslcSetSessionSettingsMemory、WslcSetSessionSettingsTimeout、WslcSetSessionSettingsVhd覆盖对应默认值即可(这些 API 的声明见 wslcsdk.h)。

完整实战:在 HelloWorld 示例中使用 WslcInitSessionSettings

官方 C 语言示例 doc/samples/WSLC-HelloWorld/helloworld.c 展示了从会话初始化到运行容器内进程的完整链路,其中会话初始化部分如下:

// 将存储目录放在可执行文件旁的 "WslcStorage" 文件夹,避免硬编码绝对路径 static void GetStoragePath(wchar_t* buffer, size_t count) { wchar_t exePath[MAX_PATH]; wchar_t* lastSlash; GetModuleFileNameW(NULL, exePath, MAX_PATH); lastSlash = wcsrchr(exePath, L'\\'); if (lastSlash != NULL) { *(lastSlash + 1) = L'\0'; } swprintf(buffer, count, L"%sWslcStorage", exePath); } int wmain(void) { // ... WslcSessionSettings sessionSettings; wchar_t storagePath[MAX_PATH]; hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) { /* 处理错误 */ } // ---- Session ---- GetStoragePath(storagePath, ARRAYSIZE(storagePath)); hr = WslcInitSessionSettings(L"WSLCHelloWorld", storagePath, &sessionSettings); if (FAILED(hr)) { PrintError(L"Init session settings", hr, NULL); goto cleanup; } hr = WslcCreateSession(&sessionSettings, &session, &error); if (FAILED(hr)) { PrintError(L"Create session", hr, error); goto cleanup; } // ... 拉取镜像、创建容器、运行进程 ... cleanup: // 结束会话:终止 + 释放 if (session != NULL) { WslcTerminateSession(session); WslcReleaseSession(session); } CoUninitialize(); return result; }

示例中包含几个值得复用的工程实践:

  1. COM 初始化:WslcInitSessionSettings及其后续 API 运行在 COM 之上,调用前需CoInitializeEx(NULL, COINIT_MULTITHREADED),结束时CoUninitialize();
  2. 存储路径的动态推导:通过GetModuleFileNameW在可执行文件旁生成WslcStorage目录,使示例不依赖硬编码绝对路径,也演示了“路径不存在会自动创建”的特性;
  3. 错误处理与资源清理:每个 API 调用后检查FAILED(hr),出错时通过goto cleanup统一回收资源;会话结束时先WslcTerminateSession再WslcReleaseSession。

示例对应的构建说明与运行方式详见 WSLC-HelloWorld 的 README。

测试验证:SDK 测试如何覆盖初始化路径

test/windows/WslcSdkTests.cpp 中的 WSLC SDK 测试类把WslcInitSessionSettings作为测试夹具的起点,直接验证了“初始化 + 覆盖默认值 + 创建会话”的完整模式:

TEST_CLASS_SETUP(TestClassSetup) { THROW_IF_WIN32_ERROR(WSAStartup(MAKEWORD(2, 2), &m_wsadata)); m_storagePath = std::filesystem::current_path() / "test-storage"; // Build session settings using the WSLC SDK. WslcSessionSettings sessionSettings; VERIFY_SUCCEEDED(WslcInitSessionSettings(c_testSessionName, m_storagePath.c_str(), &sessionSettings)); VERIFY_SUCCEEDED(WslcSetSessionSettingsCpuCount(&sessionSettings, 4)); VERIFY_SUCCEEDED(WslcSetSessionSettingsMemory(&sessionSettings, 2048)); VERIFY_SUCCEEDED(WslcSetSessionSettingsTimeout(&sessionSettings, 30 * 1000)); WslcVhdRequirements vhdReqs{}; vhdReqs.sizeBytes = 4096ull * 1024 * 1024; // 4 GB vhdReqs.type = WSLC_VHD_TYPE_DYNAMIC; VERIFY_SUCCEEDED(WslcSetSessionSettingsVhd(&sessionSettings, &vhdReqs)); VERIFY_SUCCEEDED(WslcCreateSession(&sessionSettings, &m_defaultSession, nullptr)); // ... }

该用例清晰地演示了“初始化 → 逐个覆盖默认资源 → 创建会话”的推荐调用次序。测试套件中还包含多个围绕会话生命周期与配置的独立用例,例如:

  • CreateSession测试使用独立存储目录wslc-extra-session-storage创建wslc-extra-session(WslcSdkTests.cpp);
  • 会话终止事件、崩溃回调、VHD 配置(wslc-vhd-test)、GPU 特性(wslc-gpu-test)等场景均以WslcInitSessionSettings为前置步骤(WslcSdkTests.cpp、L362、L2104、L2711)。

这说明WslcInitSessionSettings是全部会话级能力(资源规格、超时、VHD、特性开关、终止事件、崩溃转储订阅)统一的入口配置点,任何会话级功能测试都始于对它的调用。

初始化之后的会话设置 API 家族

WslcInitSessionSettings只负责写入名称、存储路径与默认值,进一步的定制依赖 wslcsdk.h 中声明的一组可选设置 API:

API作用
WslcSetSessionSettingsCpuCount设置会话 vCPU 数量(传 0 恢复默认值 2)
WslcSetSessionSettingsMemory设置会话内存,单位 MB(传 0 恢复默认值 2000)
WslcSetSessionSettingsTimeout设置启动超时,单位 ms(默认 300000)
WslcSetSessionSettingsVhd设置会话存储 VHD 的需求(容量、类型)
WslcSetSessionSettingsFeatureFlags设置会话特性标志(如WSLC_SESSION_FEATURE_FLAG_ENABLE_GPU,值为0x00000004)

例如从 WslcSetSessionSettingsCpuCount 的实现 可以看出,传入非零值则覆盖,传 0 则回退到s_DefaultCPUCount:

STDAPI WslcSetSessionSettingsCpuCount(_In_ WslcSessionSettings* sessionSettings, _In_ uint32_t cpuCount) try { auto internalType = CheckAndGetInternalType(sessionSettings); if (cpuCount) { internalType->cpuCount = cpuCount; } else { internalType->cpuCount = s_DefaultCPUCount; } return S_OK; } CATCH_RETURN();

设置完成后,通过WslcCreateSession真正创建会话,并在此后通过WslcTerminateSession与WslcReleaseSession结束会话。完整的会话 API 列表与各自文档入口见 Session APIs 索引,一个贯通全部步骤的端到端示例见 end-to-end-example.md。

使用要点小结

  • WslcInitSessionSettings是 WSLC 会话生命周期的第一步,负责写入会话名称、存储路径并填充 CPU/内存/超时/存储的默认值,本身不执行任何重操作;
  • 传入NULL的name或storagePath将得到E_POINTER;同名会话冲突(ERROR_ALREADY_EXISTS)发生在后续的WslcCreateSession;
  • 会话名称既是显示名又是机器级键,且会话名称、创建者 SID、创建进程 PID 对全机器用户可见,严禁把凭据或敏感信息放入会话名称;
  • 存储路径不存在时会自动创建,合理的路径规划(绝对路径、复用存储目录)有助于镜像缓存复用与降低启动开销;
  • 默认资源规格(2 CPU / 2000 MB 内存 / 300000 ms 超时 / 32 GB 存储)在初始化阶段即已生效,可通过WslcSetSessionSettings*系列 API 覆盖,传 0 可回退默认值;
  • 调用前需完成 COM 初始化(CoInitializeEx),会话结束时应依次调用WslcTerminateSession与WslcReleaseSession释放资源。

【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询