news 2026/10/5 11:30:23

Windows内核防火墙驱动开发:从WFP架构到SuperDriver落地实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Windows内核防火墙驱动开发:从WFP架构到SuperDriver落地实践

简介:WFP(Windows过滤平台)网络驱动防火墙源码包,面向Windows驱动开发、网络安全研究与内核编程学习者。资源围绕Windows平台下的防火墙过滤机制展开,展示如何基于WFP框架构建网络驱动层拦截与管控逻辑,适合需要参考驱动级安全方案或进行二次开发的工程师。对于初学驱动编程的人,这份代码也能作为理解WFP核心概念的起步模板,帮助厘清驱动注册、过滤条件、进程/端口绑定等常见环节。压缩包体积约766KB,属于轻量级示例代码,便于快速阅读与移植;由于平台暂未提供文件总数与具体类型明细,包内源码结构需下载后自行查看。资料目前已有283人学习,可帮助理解WFP函数调用流程、过滤层挂载方式以及驱动与防火墙交互的常见实现思路,也可作为课程设计或产品预研的起点。

1. 从SuperDriver到Windows防火墙:WFP驱动的价值落在哪?

SuperDriver这个项目代号背后,是一类很明确的诉求:在Windows上做一个由内核驱动支撑的防火墙,而WFP即Windows Filtering Platform(Windows过滤平台),就是这条技术路线的地基。普通应用层防火墙能拦网卡数据吗?能,但进程一旦被结束,规则随之失效;攻击者也能通过注入或提权绕过它的钩子。把拦截点下沉到内核态,交给TCP/IP协议栈的必经路径,失败的代价会高得多。这篇文章要讲的是SuperDriver这类驱动从零到落地的一条完整路径:先讲清楚为什么选WFP而不是旧方案,再给出最小驱动、规则引擎和黑白名单设计,最后把我在真实开发中踩过的坑按“现象-原因-解决”梳理出来。适合正在学习Windows内核网络过滤、或者准备做企业终端安全、EDR外联管控的工程师。

2. 为什么防火墙驱动一定要选WFP:绕开NDIS与TDI的三个理由

WFP并不是唯一的历史选项。在Vista之前,想做内核态防火墙通常走TDI或NDIS过滤驱动;TDI方案要自己解析协议头,NDIS过滤驱动则工作在网卡层,处理流量的位置太低。WFP从Vista开始成为微软主推的统一网络过滤架构,直到Win11依然是系统原生支持的过滤框架之一。如果你现在还要评估“用SuperDriver做防火墙该选哪种驱动”,结论基本不需要犹豫:选WFP。

2.1 WFP的分层过滤与callout机制到底怎么工作

WFP的核心思路是把网络数据在协议栈中的路径切成若干个“层”(layer)。IPv4出站、IPv4入站、转发、ALE授权连接、ALE授权接收、IPsec等都有独立层ID。每个层上挂着两类对象:过滤器和callout。过滤器描述“什么样流量在什么条件下要做什么动作”,callout则是一段有业务逻辑的回调代码。当数据经过某层时,过滤引擎把满足条件的流量交给对应的callout,callout内部的classify函数最终返回放行或拦截。

我一般把WFP比作一条流水线检查表:数据包每到一个工位(层),检查表(过滤条件)命中后,就叫对应岗位的工人(callout)来判定。判定结果不是只有拦和放,还可以挂起、直通、继续由下层处理。Windows自带防火墙本身就是基于WFP做的,第三方的WFP驱动可以注册自己的子层和callout,和系统防火墙平级工作。

这里有个关键区别:只注册callout并不会影响任何流量,真正触发callout的是过滤器。过滤器可以来自驱动自身,也可以来自用户态配置程序。配置程序打开过滤引擎后,添加一条过滤器,动作选择“调用callout”,并指定callout ID和一组条件字段,那么后续数据才会进到你的classify函数里。

WFP在内核态为开发者暴露了一组稳定的API,用户态也有一组几乎等价的API。内核态负责流量判定,用户态负责策略管理,两层通过同一个引擎协作。这使得防火墙策略可以集中托管在系统服务中,驱动崩溃不会直接影响保存的配置,这也是SuperDriver采用“内核callout + 用户态管理程序”这套成熟架构的原因。

2.2 与NDIS/TDI对比,以及“关闭防火墙有影响吗”的实际答案

我之前维护过一个老项目,用的是NDIS中间层驱动。它的优势是能覆盖更老的系统,但问题很明显:工作在网卡驱动之上、协议栈之下,所有包都是裸的以太网帧,要自己解析IP、端口、协议,还要处理分片重组。一旦协议解析有疏漏,性能和正确性就会失衡。TDI则更老,主要面向TCP/UDP会话,后来也被微软放弃了。

把WFP、NDIS中间层、TDI放在一张对比表里看得更清楚:

对比项WFPNDIS中间层TDI
系统支持Vista起全系,Win11下依然是推荐路线仍可用,微软不推荐新开发已废弃
数据可见度已解析好的IP/端口/协议字段原始帧,自行解析会话级,不适用于IP层
用户态配合同一套引擎,配置天然统一需要额外通信把规则传给驱动难以和现代防火墙兼容
状态跟踪ALE层自带连接状态自己维护连接表有,但仅限TCP/UDP
开发成本中高,但上限高高,坑多没必要再学
适合场景现代防火墙/EDR外联管控老旧系统兼容历史遗留项目

关于网上经常搜到的“关闭防火墙有影响吗”,这个问题在WFP架构下有个容易被误解的地方:如果第三方防火墙是基于WFP的,你在系统设置里把“Windows防火墙”关掉,并不会关闭WFP引擎本身,也不会让你的SuperDriver失效。因为Windows防火墙只是WFP引擎里的一组过滤器和策略,它和你注册的callout是并列关系。关掉系统防火墙,你注册的过滤逻辑还在协议栈路径上继续执行。这也是很多企业终端管理软件敢直接接管系统防火墙的底气:自带的Windows防火墙与第三方WFP驱动并不互斥,反而是可以叠加的。如果你问的是“把SuperDriver这个第三方防火墙关了会有影响吗”,那当然有,规则不再被加载,流量全部走默认放行策略;但至少要知道,自己注册的callout不会因为系统防火墙的开关而被卸载,这是排查问题时的起点。

3. 搭建SuperDriver最小驱动:从DriverEntry到第一个可拦截流量的callout

理论讲再多,不如先跑通一条最小链路。这个最小链路包括三个动作:内核驱动注册callout、用户态程序向引擎添加过滤器、实际流量触发分类回调。下面我按这个顺序拆开写,代码以C/C++为主,环境是Visual Studio + WDK,目标系统Win11 x64。

3.1 驱动入口与WFP callout注册

先看驱动里最核心的一段。一般我会创建一个WDF驱动程序,在DeviceIoControl里同时做IRP分发,但WFP相关代码跟IRP无关,只需在DriverEntry里注册callout即可。以下是一个精简但能编译通过的DriverEntry片段:

#include <ntddk.h> #include <fwpsk.h> #include <fwpmk.h> #define SUPERDRIVER_TAG 'pDSx' static UINT32 g_calloutId = 0; // 分类回调:所有被过滤器命中的流量都会进到这里 static void SuperDriverClassify( const FWPS_INCOMING_VALUES0* inFixed, const FWPS_INCOMING_METADATA_VALUES0* inMeta, void* layerData, const void* classifyContext, const FWPS_FILTER0* filter, UINT64 flowContext, FWPS_CLASSIFY_OUT0* classifyOut) { // 默认拦截,只有明确命中放行规则的流量才放行 classifyOut->actionType = FWP_ACTION_BLOCK; } NTSTATUS SuperDriverNotify( FWPS_CALLOUT_NOTIFY_TYPE notifyType, const GUID* filterKey, FWPS_FILTER0* filter) { if (notifyType == FWPS_CALLOUT_NOTIFY_ADD_FILTER) { // 过滤器添加时,这里可以预先做一些规则相关初始化 } return STATUS_SUCCESS; } NTSTATUS DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING registryPath) { NTSTATUS status; FWPS_CALLOUT0 callout = {0}; FWPM_CALLOUT0 m = {0}; UNREFERENCED_PARAMETER(registryPath); callout.flowDeleteFn = NULL; callout.notifyFn = SuperDriverNotify; callout.classifyFn = SuperDriverClassify; status = FwpsCalloutRegister0(driverObject, &callout, &g_calloutId); if (!NT_SUCCESS(status)) { return status; } m.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4; m.calloutId = g_calloutId; // displayData用于在监控工具里展示callout名称 m.displayData.name = L"SuperDriver ALE Connect Callout"; m.displayData.description = L"Block/Allow outbound connections"; status = FwpmCalloutAdd0(NULL, &m, NULL, NULL); return status; }

这段代码里有个需要特别注意的地方:FwpmCalloutAdd0的引擎句柄传的是NULL。这个API从内核态调用时,如果句柄为空,系统会尝试使用当前进程的默认会话,很多刚学WFP的人在这里会拿一个无效句柄导致添加失败。我一般会选择把callout注册放在驱动里,而callout的Add操作放到用户态管理程序里做,这样引擎句柄和事务控制都在用户态完成,更符合微软推荐的“用户态管理、内核态执行”模型。

这段代码还说明了一个关键点:即使callout注册成功,如果不添加过滤器,classify函数前面没有任何流量会进来,这叫“只挂号不看诊”。所以下一步必须在引擎里添加过滤器。

3.2 用户态添加过滤器:让classify真正被调用

用户态代码用C++,链接fwpuclnt.lib。下面是我常用的“添加一条出站拦截规则”的代码,它把TCP 443端口的所有流出连接交给SuperDriver的callout处理:

#include <windows.h> #include <fwpmu.h> #pragma comment(lib, "fwpuclnt.lib") bool AddConnectFilter() { HANDLE engine = NULL; FWPM_SESSION0 session = {0}; FWPM_FILTER0 filter = {0}; FWPM_FILTER_CONDITION0 conds[2] = {0}; DWORD result; // 动态会话:进程退出后过滤器自动清除,调试时不容易残留 session.flags = FWPM_SESSION_FLAG_DYNAMIC; result = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine); if (result != ERROR_SUCCESS) return false; filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; filter.displayData.name = L"SuperDriver Block 443"; filter.action.type = FWP_ACTION_CALLOUT_TERMINATING; filter.action.calloutKey = SUPERDRIVER_CALLOUT_GUID; filter.weight = 0x100; conds[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT; conds[0].matchType = FWP_MATCH_EQUAL; conds[0].conditionValue.uint16 = 443; conds[1].fieldKey = FWPM_CONDITION_IP_PROTOCOL; conds[1].matchType = FWP_MATCH_EQUAL; conds[1].conditionValue.uint8 = IPPROTO_TCP; filter.filterCondition = conds; filter.numFilterConditions = 2; result = FwpmFilterAdd0(engine, &filter, NULL, NULL); FwpmEngineClose0(engine); return result == ERROR_SUCCESS; }

这里有两个容易踩坑的参数。第一是filter.weight,它决定同一层里多个过滤器的优先级,权重越大优先级越高;如果系统里已经有别的防火墙,你的规则可能在它后面执行,action类型选择FWP_ACTION_CALLOUT_TERMINATING,表示命中你的callout之后终止后续规则处理,相当于把决定权完全收到SuperDriver手里。第二是条件字段类型,FWPM_CONDITION_IP_REMOTE_PORT对应的是uint16,协议字段uint8,写错类型会让条件匹配结果直接错乱。

运行到这里,SuperDriver已经具备“拦截指定连接”的最小能力。把它做成一套产品,还需要规则引擎。下一章就处理这个。

4. 把规则引擎做成黑白名单:从四元组匹配到配置“导包”落地

规则引擎是防火墙的头脑。WFP引擎本身提供了非常快的内核态条件匹配,但业务规则是动态的:企业要一键放行某个网段,研发要临时屏蔽某个IP,这些不能靠改代码重新编译。因此SuperDriver要把规则维护在内核里,再提供一套用户态接口来增删改查。

4.1 黑白名单的数据结构与匹配优先级

黑白名单是老生常谈,但设计时有两个细节经常被忽略:规则优先级和命中后的动作。我的习惯是给每条规则一个rank,数值小的先匹配;黑白名单同时存在时,白名单rank更小,先命中白名单即放行,剩下没命中的流量再看黑名单,最后落到默认策略。

下面是一张典型规则表:

字段类型示例说明
direction枚举outbound / inbound / forward匹配流量方向
protocol枚举tcp / udp / icmp / any协议过滤
localIp字符串或IPv4192.168.1.0/24本地地址或网段
remoteIp字符串或IPv410.0.0.0/8远端地址或网段
localPortuint168080应用层端口
remotePortuint16443远端端口
action枚举allow / block动作
rankuint32100越小越先匹配
enabledbooltrue是否启用

内核态不适合直接存字符串,我一般把规则编码成二进制结构体,IP地址用网络序的UINT32存,网段则拆成“起始地址+掩码长度”两个字段。内核维护一个数组,classify函数按rank排序后线性遍历。规则量少时线性遍历足够,上千条规则后可以按端口或网段建哈希索引,但这属于优化阶段的事,第一版别过度设计。

对应的C结构体可以是:

typedef struct _SUPERDRIVER_RULE { UINT32 rank; BOOLEAN enabled; UINT8 direction; // 0=in 1=out 2=forward UINT8 protocol; // IPPROTO_TCP/UDP/ICMP/0=any UINT8 action; // 0=block 1=allow UINT32 localAddr; UINT32 localMask; UINT32 remoteAddr; UINT32 remoteMask; UINT16 localPort; UINT16 remotePort; } SUPERDRIVER_RULE;

classify函数里拿到流量后,从FWPS_INCOMING_VALUES0中提取对应字段,依次比较。如果协议字段是any,就跳过协议匹配;端口是0,表示不限制端口;IP和掩码配合可以匹配网段。比较时我特别强调一下:WFP字段里的IP地址是网络字节序,而Windows内核常用主机字节序,千万不能直接拿内存值比较,建议统一转成主机序再比较,避免在大小端上翻车。

黑白名单的语义要明确:先按rank跑一遍所有启用规则,第一条命中的规则决定动作;如果整张表都没有命中,执行默认策略。企业防火墙默认策略通常是“白名单模式下默认拦截,黑名单模式下默认放行”。SuperDriver的classify函数里,我默认把actionType设为FWP_ACTION_BLOCK,然后遍历规则,命中允许规则就改成FWP_ACTION_PERMIT,这与“先白名单后黑名单”是一致的。

4.2 与用户态联动的配置下发与“导包”落地

规则要能从外部注入到内核。常见做法是创建设备对象和IOCTL,SuperDriver创建一个\Device\SuperDriverFw设备,用户态用CreateFile + DeviceIoControl发送规则。下面是接收“添加规则”的IRP处理片段:

NTSTATUS SuperDriverDeviceControl(PDEVICE_OBJECT device, PIRP irp) { PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp); ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; PVOID inBuf = irp->AssociatedIrp.SystemBuffer; ULONG inLen = stack->Parameters.DeviceIoControl.InputBufferLength; if (code == IOCTL_SUPERDRIVER_ADD_RULE && inLen == sizeof(SUPERDRIVER_RULE)) { SUPERDRIVER_RULE* rule = (SUPERDRIVER_RULE*)inBuf; NTSTATUS status = SuperDriverAddRule(rule); irp->IoStatus.Status = status; } IoCompleteRequest(irp, IO_NO_INCREMENT); return irp->IoStatus.Status; }

SuperDriverAddRule内部会先取一个自旋锁,再把规则追加到全局数组末尾。注意IOCTL的Buffer是SystemBuffer,用户态下发时直接传结构体指针,不要传带指针的链式结构;如果规则里带了变长字符串,我建议改用固定长度上限,序列化时统一按字节数组传,避免内核态解析字符串的各种边界麻烦。

规则导入导出是产品化必须的“导包”能力。用户态把当前所有规则按一个JSON格式包导出来,再在另一台机器上导入。这个包只保存业务层规则,不保存内核状态;导入时逐条调用IOCTL_ADD_RULE,先清空再添加。JSON里的IP网段、协议、动作等字段做严格校验,非法值直接拒绝,避免导包文件被篡改后在内核里产生意想不到的匹配结果。我遇到过一种情况,让用户导出的包在导入时把IPv6地址字符串截断,会解析出错误规则,这一点后面避坑章还会展开。

规则更新时机也值得注意。如果classify函数正在遍历规则数组,用户态同时插入新规则,会读到半新的状态。我在设计里用读写锁:classify走读锁,规则增删走写锁。WFP分类回调运行在DISPATCH_LEVEL上,不能直接拿快速锁,所以更建议在classify里先把当前规则快照复制到一个局部副本,再基于副本做匹配。这个细节做到位,动态下发规则时才不会蓝屏。

5. WFP驱动常见问题排查:从0x800706d9到分类回调不触发

这一章是硬通货。标题里出现了firewall和wfp,实际开发中八成时间不是在写过滤逻辑,而是在查基础设施问题。这里列出几条我踩过、也看同事踩过的坑,每条都按“现象 → 原因 → 解决”写清楚。

5.1 现象:FwpmEngineOpen0返回0x800706d9

刚搭好用户态管理程序,一执行就报“操作失败”,错误码0x800706d9。网上一搜,大家都在说Win11防火墙错误代码0x800706d9。这个错误经常被理解成“Windows防火墙坏了”,但在WFP开发里还有另一层含义:FwpmEngineOpen0实际是通过RPC连接Base Filtering Engine(BFE)服务,如果这个服务处于禁用或启动失败状态,打开引擎就会返回这个错误码。

解决路径:先在管理员PowerShell里执行Get-Service BFE确认服务状态,如果停止就Start-Service BFE。如果服务启动失败,去事件查看器看System日志里BFE依赖的服务,比如PolicyAgent(IPsec Policy Agent)是否被禁用了。做完之后重启SuperDriver的配置程序,基本就好了。这个坑最容易发生在刚装好的Win11虚拟机里,有人为了“优化系统”把一堆服务禁用掉,BFE也在其列。

5.2 现象:Win11下驱动加载失败,提示“无法验证发布者”

使用测试证书编译出来的SuperDriver,在Win11实机上装不上,事件管理器里显示“驱动程序无法验证数字签名”。原因是近年Windows对内核驱动签名策略收紧了要求,测试签名证书只对开启了测试签名模式的系统有效。

解决:把开发机切到测试签名模式,管理员命令行执行bcdedit /set testsigning on然后重启。如果连测试模式都没开,用signtool对.sys文件做签名后再尝试加载。注意不要用吊销的证书,内核会拒绝。还有一个被忽略的细节:WDK自带的INF文件里CatalogFile节点必须指向实际的.cat文件,否则签名校验过不了。这个问题不做提前准备,等驱动写完了再去排,真的很浪费时间。

5.3 现象:callout注册成功,但classify函数就是不回调

这个坑我见过至少三次。在用户态执行FwpmFilterAdd0,返回成功;抓包也能看到流量在走,但SuperDriverClassify就是不执行。原因在于过滤器的action.type可能不是callout类,常见的错误是把action.type设成FWP_ACTION_BLOCK或FWP_ACTION_PERMIT,那样流量被引擎自己拦掉或直通,永远不会进callout。

解决:把action.type改为FWP_ACTION_CALLOUT_TERMINATING,同时action.calloutKey要填对全局唯一GUID。如果GUID不一致,FwpmFilterAdd0也会报错;但最隐蔽的是GUID一致、层不一致——callout注册在ALE_AUTH_CONNECT_V4,过滤器却加到OUTBOUND_IPPACKET_V4,那也不会进你的回调。所以排查时先确认callout的applicableLayer和filter.layerKey完全一致。

5.4 现象:规则下发后用一会儿就消失,重启后全部丢失

之前为了调试方便,在FWPM_SESSION0里设置了FWPM_SESSION_FLAG_DYNAMIC。动态会话的过滤器在进程退出时自动删除,所以SuperDriver配置程序一关,规则全部没了。这在开发期很方便,但产品化之后是事故。

解决:动态会话只用于开发调试;正式安装版要用持久化会话,且在FwpmFilterAdd0前开启一个事务,FwpmTransactionBegin0 + FwpmFilterAdd0 + FwpmTransactionCommit0,让规则写入到系统持久化存储中。另一层保险是SuperDriver自己把规则备份到一个配置文件里,服务启动时重新加载,避免WFP存储异常导致规则丢失。

5.5 现象:接入SuperDriver后,访问网页卡顿或者大流量拖垮CPU

某次在测试机上装完驱动,打开浏览器要等好几秒。问题出在classify函数里做了太多事情:每次TCP连接都查一次注册表、读一次数据库、还要做一次证书解析。WFP分类回调运行在协议栈关键路径上,任何慢操作都会直接拖垮网络。

解决:把classify里能前置的过滤条件全部用WFP引擎的条件字段完成,比如IP、端口、协议用FWPM_FILTER0去匹配,让引擎在进callout之前就丢掉大部分流量;只把那些需要业务逻辑的流量交给callout。如果确实需要做耗时的内容检查,可以记录待处理队列,等用户态拿结果后再决定放行还是拦截。另外注意不要在DISPATCH_LEVEL主动睡眠或锁大自旋区,这是蓝屏的典型来源。

6. 进阶:让过滤粒度变粗,同一层只裁决一次

如果你已经跑通上面的最小链路,下一个优化方向是把过滤粒度从“每个包”提升到“每条连接”。ALE层(Application Layer Enforcement)是WFP专门为连接层过滤设计的,一条TCP连接只在建立时经过ALE_AUTH_CONNECT_V4或ALE_AUTH_RECV_ACCEPT_V4,之后的数据包不再重复进classify。与其在OUTBOUND_IPPACKET_V4这种包级层里逐包遍历规则,不如在ALE层把连接裁决完,然后在classifyOut里直接返回FWP_ACTION_PERMIT。

常见做法是结合流上下文:在ALE层首次命中时,把SuperDriver的流上下文和连接绑定,后续该连接的所有数据包无需再走业务规则。这个操作的收益很明显——一个网页几十个小连接,如果每个包都走一遍规则,CPU开销会高一个数量级;而只裁决每一条连接的建立,规则引擎的负载就下来了。

验证SuperDriver是否生效,我通常做一轮干净的端到端测试:先在测试机上关闭系统自带防火墙,验证“关掉自带防火墙有没有影响”,再加载SuperDriver并下发一条拦截外网TCP 443的规则,然后依次做三件事。第一,用tcping或curl访问一个HTTPS站点,连接超时,说明出站被拦;第二,把规则改成只允许特定IP网段,正常访问网段内站点,访问网段外站点失败;第三,在抓包工具里看,SYN包发出去但收不到SYN/ACK,证明拦截点位于协议栈核心路径而不是用户态。

最后说个我的教训。WFP驱动的签名和BFE依赖问题,一定要在项目第一天就准备好基础环境,别等代码写完才去开测试签名模式。养成每次改动后用signtool重新签名、实机验证一轮的习惯,比事后排查快得多。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 11:27:48

Excel双表数据双向同步:VBA Change事件实战与避坑指南

前阵子帮一个做渠道运营的朋友改表&#xff0c;她手里有两份Excel&#xff1a;一份是渠道名单总表&#xff0c;一份是按月度拆分给各区域的跟进表。两份表里都有“当前状态”和“最新联系人”这两列&#xff0c;两边都会改。她说每次月底对账&#xff0c;都需要人工把两份表同一…

作者头像 李华
网站建设 2026/10/5 11:25:25

交通标志识别鲁棒性实战:光照、尺度与几何校正三重优化

简介&#xff1a;本资源是一个面向计算机视觉初学者与智能交通系统开发者的Python深度学习实战项目&#xff0c;聚焦交通标志识别这一典型图像分类任务&#xff0c;适用于课程设计、毕业设计及辅助驾驶算法入门实践。压缩包共28个文件&#xff0c;总计234KB&#xff0c;包含6个…

作者头像 李华
网站建设 2026/10/5 11:23:40

AI产品经理实战指南:从认知底层到判断力构建

1. 这套748集教程到底在教什么&#xff1f;先撕开“AI产品经理”这个标签很多人看到标题里“AI产品经理”四个字&#xff0c;第一反应是&#xff1a;这不就是个挂羊头卖狗肉的岗位&#xff1f;要么是把传统PM包装成AI版&#xff0c;要么是让程序员硬转岗去画原型、写PRD。但实测…

作者头像 李华
网站建设 2026/10/5 11:23:23

OpenShell:一个让终端效率翻倍的会话工作台实测指南

我先说个真实的场景&#xff1a;每天打开终端&#xff0c;你是不是也这样——一堆标签页开着&#xff0c;分不清哪个窗口跑的是哪个服务&#xff1b;想复用之前敲过的一条长命令&#xff0c;翻半天历史记录&#xff1b;换台电脑&#xff0c;所有的别名、环境变量、脚本片段全得…

作者头像 李华
网站建设 2026/10/5 11:22:08

旅游情感分析毕业设计:ABSA语料清洗与方面标注实战指南

简介&#xff1a;本资源是一套面向计算机专业本科生的毕业设计完整实现方案&#xff0c;聚焦旅游景点评论的细粒度情感分析任务&#xff0c;适用于自然语言处理课程设计、毕设开题与系统开发实践。项目基于Python构建Django Web应用&#xff0c;集成RNCC情感分类模型&#xff0…

作者头像 李华
网站建设 2026/10/5 11:22:06

Python技巧分享

在本文我将会分享我在python里面经常用的使用技巧 如果你觉得有用就点个赞 1.用字典代替if-else 我们在做python项目的时候经常会遇到格式相同 但是数据不同的情况 我们可以把所有可能性存成一个字典 然后填上触发条件 比如 我这里有个试例 #假设你要解析一段数据 数据的格式总…

作者头像 李华