尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

VS 2019+Win10+VMware 内核双机调试环境搭建与避坑

发布时间:2026/9/29 7:07:35

资讯中心
01
ARTICLE

VS 2019+Win10+VMware 内核双机调试环境搭建与避坑

VS 2019+Win10+VMware 内核双机调试环境搭建与避坑
大概前年冬天我为了调一个文件系统过滤驱动连续三个晚上把自己主力机上跑的 Windows 搞成蓝屏循环最后一次连安全模式都进不去只能拿安装盘修复。那之后我把整套调试环境搬进了虚拟机主机跑 VS 2019VMware 里跑一台 Win10 当靶机从此再没因为调试崩过自己的开发机。这篇就把 VS 2019 Win10 VMware 双机调试这条链路从头写一遍包括 WDK 和 SDK 的版本匹配、虚拟机的几个关键开关、目标机 bcdedit 的逐条配置、VS 里附加内核调试的完整操作以及我在过去两年里踩过的、文档上基本不会提的那些坑。写驱动、做内核过滤、或者单纯想学内核调试的都能照着搭出一套能用的环境。1. 为什么这套组合值得花半个晚上搭起来1.1 单机调试最大的问题断点一命中整台机器就停住了很多人第一次接触内核调试会直接在开发机上开bcdedit /debug on然后用 WinDbg 连本机。这条路走起来很快十分钟就能看到kd提示符但它有个致命限制本地内核调试是只读的。你能看进程列表、能!analyze崩溃转储、能读内存但你没法设断点、没法单步、没法让系统停在某个函数的入口。新手最常见的困惑就是我断点打成空心圈怎么点都不命中其实不是操作错了而是本地内核调试根本不支持打断点这个能力必须由另一台机器提供。真正在物理机上做双机调试的体验也不舒服。内核断点命中时目标机的所有 CPU 都会被停住键盘鼠标全部失去响应你只能靠另一台机器上的调试器把系统g起来。更难受的是驱动一旦在启动早期崩掉目标机可能连登录界面都到不了你只能进安全模式、删服务、或者挂载离线注册表把驱动禁用掉。我那次蓝屏循环就是这么来的——驱动在DriverEntry里访问了还没准备好的设备对象系统每次启动都崩在同一个位置反复重启完全是死循环。1.2 虚拟机带来的三件事快照、克隆、随时重装换成 VMware 里的 Win10 目标机以后上面这些问题全部降级成了点两下鼠标。VMware 的快照功能可以在几秒钟内把整台虚拟机回滚到任意时间点包括 BCD 配置、驱动文件、注册表、事件日志全都一起回滚。调试那种一崩就起不来的驱动时我的标准动作是跑一次崩了回滚快照改代码再跑。整个过程不需要重启物理机也不需要重装系统。克隆同样重要。当你需要在干净的 Win10和装满了调试环境的 Win10之间反复切换时克隆一份虚拟机比重新装系统快几十倍。再往后一点如果你要同时调两个不同版本的内核比如对比 19041 和 22621 的行为差异多开一台靶机就完事了宿主机上的 VS 只要在目标计算机列表里切换一下即可。还有一个隐性收益是隔离。内核调试会让目标机的时钟在断点期间停止走动任何依赖时间的服务都会莫名其妙超时调试过程中还会大量写日志、拉高 CPU、把内存搅乱。这些事情发生在你自己的主力开发机上会直接污染你的日常工作放在虚拟机里最坏结果也就是把虚拟机搞崩重开一个干净快照继续。1.3 VS 2019 当调试前端顺手但要知道它的边界Visual Studio 2019 加上 WDK 之后驱动开发这一套是打通的新建驱动项目、写代码、生成.sys、部署到目标机、附加内核调试、在源码里点断点单步全在一个界面里完成。变量监视、调用堆栈、模块列表这些窗口和写用户态程序是一样的操作习惯对刚从应用层转过来的人特别友好不用一上来就背 WinDbg 的命令。但必须说清楚它的短板VS 的内核调试前端只是 KD内核调试引擎的一个图形外壳命令能力比 WinDbg 窄一大截。像!analyze -v、!pool、!irp、!devobj这些 WDK 扩展命令在 VS 里基本用不了或者很别扭。我现在的分工是写代码、下断点、单步跟逻辑、看变量全在 VS 里做一旦要分析内存结构、解析崩溃转储、或者需要跑扩展命令立刻切到 WinDbg。两个前端不要同时连着同一台目标机尤其是走串口命名管道的时候管道是一对一的会互相抢连接。2. 宿主机与目标虚拟机的环境搭建2.1 VS 2019 的组件选择和 WDK/SDK 版本匹配这一节是最容易白折腾半天的地方。VS 2019 装完之后光有 C 编译器是不够的驱动项目模板来自 WDK。正确的安装顺序是先装 Visual Studio 2019工作负载勾使用 C 的桌面开发再把 WDK 装上WDK 安装程序会自动往 VS 里注入驱动项目模板和驱动程序菜单。版本匹配是硬约束也是最大的坑WDK 的主版本号必须和 Windows SDK 对得上比如 WDK 对应 10.0.19041 那一版就必须配同一版的 SDK装成 10.0.18362 或者更新的 22xxx 都会出问题。更关键的是Windows 10 2004 之后的 WDK 版本开始要求 VS 2022如果你坚持用 VS 2019就老老实实停在 19041 那一代 WDK 上别去下最新版——装完的结果就是 VS 里死活找不到驱动模板或者编译时报找不到wdk.props。判断方法很简单新建项目里搜索 Driver能看到 Empty WDM Driver 和 Kernel Mode Driver (KMDF) 这类模板说明环境对了看不到就重跑 WDK 安装程序确认勾了 Visual Studio 集成那一项。顺带把调试器也装上。WDK 的安装包里包含 Debugging Tools for Windows装完之后在C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\下能找到windbg.exe。这个 WinDbg 后面当 B 计划用得上别省这一步。2.2 VMware 侧虚拟机创建时几个真正影响调试的开关VMware Workstation 用官方渠道下载安装就行安装时以管理员身份运行安装包放在纯英文路径下。如果你以前装过旧版本先彻底卸载再装残留的虚拟网卡驱动和注册表项会让安装程序在修复阶段报找不到某个 dll这类报错基本都是安装包不完整或路径带中文引起的官方提供了一个专门的清理工具可以搜索VMware 清理工具找到并跑一遍。虚拟机本身的参数我的建议是内存 4GB 起调试 8GB 更舒服CPU 给 2 核以上磁盘 60GB 够用。处理器那一栏把虚拟化 Intel VT-x/EPT 或 AMD-V/RVI勾上——内核调试本身不依赖嵌套虚拟化但勾上以后你在靶机里跑 WSL2、Docker、或者再开一层 Hyper-V 会方便很多。不过这里要提前埋一个伏笔靶机里如果真开了 Hyper-V 和内存完整性串口调试基本会失效后面第 5 节会专门讲怎么处理这个矛盾。网卡型号选默认的 e1000e 就够了。原因很实际e1000e 是 Win10 自带驱动的网卡系统一装完就能用而 vmxnet3 需要装 VMware Tools 之后才有驱动。KDNET 网络调试要在系统启动早期就把网卡跑起来网卡驱动越原生越省事。如果你打算走串口命名管道那条路第 3.2 节需要提前给虚拟机添加一个串行端口。打开虚拟机设置添加串行端口选择使用命名管道管道名填\\.\pipe\com_1虚拟机这一端选该端是服务器另一端选应用程序并且务必勾上轮询时主动放弃 CPU。最后这个勾选项不是可有可无的命名管道串口是轮询式的不勾的话虚拟机会有一个 CPU 核心被吃满风扇狂转你还会以为是调试卡住了其实是串口在空转。2.3 靶机装完 Win10 之后必须先做的四件事第一关掉内存完整性和 VBS。路径是 Windows 安全中心 → 设备安全性 → 内核隔离 → 内存完整性关掉并重启同时在管理员命令行里执行bcdedit /set hypervisorlaunchtype off。这一步的意义在于虚拟化安全开启时串口调试通道几乎必然失效KDNET 也经常出现能连上但几十秒后掉线的现象关掉是最省时间的做法。第二打开测试签名。执行bcdedit /set testsigning on并重启。桌面右下角会出现测试模式的水印这是正常现象别去研究怎么消掉它。不开测试签名的话你自己编的驱动在net start时会直接被系统拦下来报数字签名验证失败。第三关掉休眠顺带关掉快速启动。执行powercfg /h off。快速启动是混合引导它会让关机再开机和重启两种操作走不同的引导路径而 BCD 里关于调试的改动在混合引导下有可能不生效或者表现不一致。调试环境里把这个变量消掉能省掉大量明明配了却没生效的疑惑。同时把靶机的 Windows 更新暂停掉别让它在调试到一半的时候自己重启。第四装 VMware Tools。装上之后分辨率、拖拽、共享文件夹都舒服很多。如果你遇到安装时提示继续运行脚本未能在虚拟机中成功运行这类报错通常是用旧版 Tools 配新 Win10 导致的换 VMware Workstation 自带的版本一般能过实在装不上也可以先跳过双机调试本身不依赖 Tools 的图形增强功能只走网络和串口两条通路。3. 目标 Win10 虚拟机侧把调试通道真正打开3.1 KDNET 网络调试的目标机配置与逐条解释先确定地址。宿主机的 VMware 虚拟网卡在控制面板 → 网络连接里的名字分别是VMware Network Adapter VMnet1仅主机模式和VMnet8NAT 模式。靶机用哪种网络模式就去ipconfig里看对应的那个地址那就是后面要填的hostip。如果你用的是桥接模式就用宿主机真实网卡的 IP但要注意宿主机可能有多块网卡得选那块靶机能路由到的。在靶机的管理员命令行里执行下面三条bcdedit /debug on bcdedit /dbgsettings net hostip:192.168.10.1 port:50000 key:1.2.3.4 bcdedit /enum {current}第一条开调试开关。第二条里的hostip指的是调试器所在的机器也就是宿主机不是靶机自己这一点很多人第一次会填反port是 UDP 端口50000 以上随便挑一个没被占用的就行key是四段式的口令自己随手编一个比如1.2.3.4宿主机的调试器必须填一模一样的值否则握手阶段就会被拒绝。第三条用来验证输出里应该能看到debug Yes和一列dbgsettings。我这里更推荐一种网络配置给靶机加第二张网卡专门接在仅主机模式Host-only上只用来跑内核调试。这样的话你的靶机主网卡可以随便折腾——换 NAT、换桥接、甚至故意把它弄断调试通道都不会受影响。更实际的意义是当你调的是网络协议栈或网卡驱动的时候如果调试通道和被测通道共用同一张网卡很容易出现自锁或者干扰只有物理上分开才干净。改完 BCD 之后一定要重启靶机不要关机再开机。重启过程中如果宿主机上的调试器已经进入等待状态你就能看到连接握手如果宿主机上没开调试器靶机等一小会儿会自己继续启动不会卡死。所以顺序上先开调试器还是先开靶机不是硬性的但我习惯先把调试器挂上去等这样能抓到最早期的启动日志。3.2 传统命名管道串口方案VMware 虚拟串口怎么配如果因为某些原因走不了网络比如你要调的就是网络驱动串口命名管道就是退路。虚拟机侧串口按 2.2 节的配置加好之后在靶机里执行bcdedit /debug on bcdedit /dbgsettings serial debugport:1 baudrate:115200debugport:1表示用靶机里的 COM1。这里有个细节要确认虚拟串口在来宾系统里到底映射成 COM 几取决于你添加串口的顺序去设备管理器里看一下端口COM 和 LPT确认一下最稳妥。baudrate在命名管道方案里其实没有实际意义但必须写不然 BCD 会报参数缺失。宿主机侧的 WinDbg 连接命令是windbg -k com:pipe,port\\.\pipe\com_1,resets0,reconnect这两个参数都别省。resets0是让 WinDbg 不要尝试复位管道复位会导致连接反复断开reconnect是让 WinDbg 在连接失败时反复重试靶机重启后能自动接回来不用你手动重开调试器。说句实话串口这条路我现在的使用频率很低原因在第 2.3 节提过——它和虚拟化安全功能冲突而且微软这几年的方向明显是 KDNET。不过它有一个网络调试替代不了的优点调试通道和被调试的网卡完全无关。调网卡驱动、协议栈、或者要在断点里看网络包的时候串口是唯一不干扰现场的选择。顺便提一句如果你走的是两台物理机加 USB 转串口线的老路子记得先在两边装好转换芯片的驱动CP210x、CH340 这类并在设备管理器里确认 COM 号然后按同样的debugport逻辑配置。3.3 配置完成后的连通性自检清单配完不要急着开 VS先把下面这张表逐项过一遍。我遇到过太多次折腾一晚上最后发现是防火墙的情况按顺序查能省掉大量时间。检查项怎么看期望结果调试开关是否生效bcdedit /dbgsettings显示 net 或 serial参数与设置一致当前启动项是否带调试bcdedit /enum {current}有debug Yes虚拟化安全是否关干净安全中心内核隔离 bcdedit /enum {current}内存完整性关闭无 hypervisor 抢占hostip 是否可达靶机上ping 宿主机hostip能通最好不通也不代表 KDNET 不通宿主机 UDP 入站防火墙入站规则调试端口放行端口是否被占用宿主机netstat -ano -p udp目标端口没有被其他进程占用宿主机上放行 UDP 端口的命令是netsh advfirewall firewall add rule nameKDNET-IN dirin actionallow protocolUDP localport50000要理解一个容易误解的点调试通道是靶机主动往宿主机发数据所以需要放行的是宿主机的入站 UDP靶机的防火墙一般不参与。同样ping通不通和 UDP 端口通不通是两件事ICMP 被拦不代表 KDNET 连不上反过来 ping 通了也不保证调试能连——最终验证只有一个标准就是调试器能不能挂上去。4. 宿主机侧接入VS 2019 附加内核调试的完整操作4.1 在 VS 里把目标计算机登记进去WDK 装好之后VS 2019 的菜单栏会多出驱动程序这一项。进入驱动程序 → 测试 → 配置计算机和设备在弹出的对话框里添加一台新计算机给它起个标签名比如win10-target填上靶机的 IP连接类型选网络或串口然后把端口和 key 填成和靶机bcdedit里完全一致的值。不同 WDK 小版本这个对话框的措辞和布局会有差异有的版本是先选预配计算机再填参数有的是手动配置调试器设置但核心就是四样东西标签名、连接类型、端口、key。四样对齐了就能连上对不齐就是连不上没有中间状态。另外提醒一句把 VS 以管理员身份运行内核调试需要访问底层调试通道权限不够会直接失败。4.2 生成、部署、附加三步走通第一步是生成。在项目属性里确认 Driver Settings 下的目标平台是 Windows 10、目标系统版本是 Windows 10 或更高平台选 x64配置选 Debug。生成产出是.sys、.pdb、.inf、.cat这一套文件。这里记住一件事.pdb是留给宿主机上的调试器读懂源码用的靶机上只需要.sys。第二步是部署。目标计算机配置好之后生成菜单里会出现部署命令VS 会把驱动复制到靶机的System32\drivers目录并注册服务。如果不想依赖 VS 的部署手动来也完全可以把驱动拷进靶机然后用sc create mydrv type kernel binPath C:\Windows\System32\drivers\mydrv.sys sc start mydrv注意sc create的等号后面必须有一个空格写成binPathC:\...会直接报参数错误这个坑我见过太多人踩。部署失败最常见的原因有三个靶机没开测试签名、调试通道本身不通、服务名和已有服务冲突。第三步是附加。打开调试 → 附加到进程在传输下拉框里选Windows 内核模式调试器限定符里填目标计算机的标签名或者直接填连接串net:port50000,key1.2.3.4。附加成功后进程列表里会出现一个内核项。这时候点调试 → 全部中断如果能看到调用堆栈和模块列表说明整条链路已经通了。记住一个前提同一时间只接一个调试器。如果你之前开着 WinDbg先把它关掉再用 VS 接两个前端同时挂着会互相干扰。4.3 断点打不上、空心圈的三种处理和一种进阶用法第一种情况是符号没加载。检查模块窗口里你的驱动有没有出现以及它旁边的符号状态是不是已加载。找不到符号的话八成是驱动文件在部署之后又被重新编译过.pdb的 GUID 和靶机上.sys的对不上了。规矩很简单部署之后不要再重新生成改了代码就重新走一遍生成和部署。第二种情况是驱动还没被加载。内核里的驱动不是一开始就存在于内存中的你没sc start之前断点当然命不中。这时候最省事的办法是用符号断点VS 里调试 → 新建断点 → 函数断点输入mydrv!DriverEntry驱动一加载就会停下来然后你再在源码里补上真正想要的断点。这一步等于把什么时候能打断点这个问题彻底解掉。第三种情况是断点位置在会被频繁执行的路径上比如中断处理或者 DPC 里。内核断点命中会让所有 CPU 停住如果你断在键鼠中断或者存储栈的关键路径上系统会看起来像死机而且靶机的时钟停止走动某些依赖超时的逻辑会跟着出错。遇到这类场景我更倾向于少用断点、多用条件断点符号后面加条件表达式或者干脆在驱动里临时加日志输出。最后说一个进阶用法在 VS 的调用堆栈和模块窗口配合着看能很快定位驱动崩在谁的上下文里。内核崩溃的调用栈经常是从KiSystemService或者中断入口开始一路往下中间隔着几层系统模块看到自己的驱动名字之后重点看它下面几层的参数和this指针比全栈通读效率高得多。4.4 WinDbg 作为备用方案连接命令和符号配置VS 前端搞不定的时候切 WinDbg。网络方式windbg -k net:port50000,key1.2.3.4串口命名管道方式windbg -k com:pipe,port\\.\pipe\com_1,resets0,reconnect连上以后第一件事是把符号配好不然看到的全是地址和汇编.sympath srv*C:\symbols*https://msdl.microsoft.com/download/symbols .reload lm.sympath里指定本地缓存目录的意义很大Windows 的内核符号动辄几百兆配一次缓存下来以后每次连接都是秒级。lm用来列出模块确认你的驱动和它对应的.pdb都加载上了。接下来!analyze -v看崩溃原因、!process 0 0看进程列表、g继续运行、bp和bu下断点这些是内核调试的日常操作。5. 连不上、连上又断、部署失败六个真实翻车场景的排查链路5.1 完全连不上按层排查不要瞎猜连不上是个大筐里面装着至少六种原因我固化成了一套从下往上的排查顺序每次照做基本十分钟内能定位。第一层确认靶机真的读到了配置进系统后跑bcdedit /dbgsettings如果显示的是未设置或者还是上一次的值说明改动没生效——先怀疑是不是关机再开机而不是重启同时确认已经执行过powercfg /h off。第二层确认虚拟化安全关干净了安全中心里的内存完整性关闭并且bcdedit /enum {current}的输出里没有 hypervisor 抢占的痕迹。第三层确认hostip填的是靶机能路由到的宿主机地址宿主机的多网卡环境里这一条错得最多尤其是你换了网络模式NAT 换桥接之后忘了同步改 BCD。第四层是防火墙。我遇到过一次某类安全软件静默拦截 UDP 50000 端口netsh放行规则加了也没用把安全软件临时退出后立刻就连上了。第五层是端口占用宿主机上跑netstat -ano -p udp看一下目标端口是不是被别的进程绑了选端口的时候避开常见服务占用的区间。第六层才轮到怀疑网卡把靶机网卡换成 e1000e 再试一遍。这个顺序的价值在于它把玄学变成了可以逐个排除的确定性检查项。5.2 连上几十秒就断三个高频原因第一个原因是虚拟化安全没关干净。表现很有欺骗性调试器能连上能跑几条命令然后链接莫名其妙断掉靶机还在正常运行。这种情况直接回去检查内存完整性和 hypervisor 抢占九成能解决。第二个原因是网卡的电源管理。靶机上设备管理器找到网卡属性里的电源管理选项卡把允许计算机关闭此设备以节约电源的勾去掉。内核调试通道建立早期依赖网卡保持活跃省电策略把网卡关掉通道自然就断了。同样的道理靶机的电源计划设成高性能别让它进入任何低功耗状态。第三个原因是宿主机侧的 VMware 网络。宿主机的网络在睡眠唤醒后经常会变动VMware 的虚拟网卡需要断开再连接一次或者在虚拟机设置里重新挂载一次网络适配器。同时检查一下宿主机服务里 VMware 相关的网络服务有没有在跑如果它没启动NAT 模式下靶机的网络本身就是不通的。5.3 调试结束之后怎么把靶机恢复成干净状态调试机的状态是会累积的久了你也会搞不清哪次改动导致的异常行为。我的清理清单是bcdedit /debug off关掉调试开关dbgsettings本身不用刻意删它只在调试开关打开时才生效如果这台机器要用来做别的事bcdedit /set testsigning off把测试模式关掉并重启删掉宿主机上为了调试加的入站规则把靶机的系统还原点或者快照更新一下。这里要特别提醒testsigning的状态开着测试模式的机器在安全性和行为上和你最终要发布的环境不完全一致所以发布前的最后一次验证一定要在关了测试签名、用正式签名签过的驱动上做一遍。我见过不止一次调试环境跑得好好的正式环境加载失败的情况根因就是签名策略差异。5.4 部署和服务启动失败从签名和路径查起sc start报出Windows 无法验证此文件的数字签名或者错误码 577、1275基本都是签名问题回到bcdedit /set testsigning on这条线上处理或者按 WDK 的流程用测试证书给驱动签名。如果错误提示是找不到文件或者服务无法启动先确认binPath指向的.sys真的在那个位置路径里没有多余的空格sc命令对空格极其敏感等号后面要空格值里面多一个空格也会被当成参数截断。还有一个很容易忽略的情况驱动加载失败但错误信息很含糊。这时候去靶机的事件查看器看系统日志内核驱动加载失败通常会有明确的记录比反复尝试启动服务有效得多。5.5 快照回滚之后设置消失了这是虚拟机调试特有的坑。快照回滚会连同 BCD 配置一起回滚如果你是在打完快照之后才做的bcdedit配置回滚到那个快照配置自然就没了靶机会表现得像从来没配过双机调试一样。我现在的快照策略是两级装完系统、装完 Tools、做完基础优化之后打一个叫clean-base的快照然后配置完 BCD、装好驱动开发所需环境之后再打一个叫debug-ready的快照。以后任何时候环境被搞乱了回到 debug-ready 就完事一分钟恢复。克隆虚拟机是另一个相关场景。VMware 克隆时会问我已复制该虚拟机还是我已移动该虚拟机选复制会重新生成 MAC 地址靶机拿到的 IP 可能跟着变你之前填在bcdedit里的hostip或者 VS 里登记的目标 IP 就会失效。克隆之后先看一眼 IP再做别的。5.6 两个调试环境里才有的假故障别被它们带偏方向第一个是时间停滞。断点命中期间靶机的时钟不走所有基于超时的逻辑都会莫名其妙地失败——网络连接的握手超时、服务等待超时、心跳包判定离线这些现象在你g起来之后会全部消失它们不是 bug是调试本身造成的。分析这类问题时先把断点去掉跑一遍确认现象还在再回来查代码。第二个是环境优化带来的行为差异。靶机如果按精简系统的思路关了一堆后台应用和服务、关了内存压缩行为和你真正的目标环境是有差异的。做性能或者并发相关的调试时我一般会准备两台靶机一台精简的用来快速迭代和复现崩溃一台接近真实配置的用来做最终验证。两台靶机的 BCD 配置可以完全一样但系统和驱动环境要区分开这样才不会出现调试环境永远正常上线就出问题的尴尬。另外如果你在靶机里配合使用了共享文件夹来回拷驱动注意共享文件夹依赖 VMware ToolsTools 出问题的时候文件可能是旧版本——我就遇到过反复部署却始终加载旧驱动的情况查了半小时才发现是共享文件夹缓存没刷新。后来我改成直接在 VS 里走部署或者用scp之类的命令行方式拷贝并核对文件哈希这类低级问题就再也没出现过。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。