news 2026/9/4 19:14:58

300元自制25G网卡:FPGA开源方案实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
300元自制25G网卡:FPGA开源方案实战指南

这次我们来看一个能让硬件开发者、网络工程师和学生低成本上手高端项目的方案:用大约300元的预算,实现25G网卡功能。这个方案的核心不是购买成品高速网卡,而是利用开源的FPGA项目,将一块具备高速收发器的FPGA开发板变成一个高性能的网络接口。对于想学习高速接口设计、网络协议栈实现,或者为特定应用定制网卡功能的开发者来说,这是一个极具性价比的切入点。

这个项目的重点不在于概念多复杂,而在于它是否真的能用起来,以及硬件门槛到底有多高。最核心的几个特点是:第一,成本极低,核心硬件开销可以控制在300元左右;第二,完全开源,你可以从GitHub等平台获取完整的代码和文档;第三,它不仅仅是一个“网卡”,更是一个高速接口的实践平台,你可以基于此实现PCIe、以太网、甚至自定义的串行协议。本文将带你了解如何选择硬件、搭建环境、部署开源项目,并最终验证网卡的基本功能。如果你关心FPGA开发、高速数字设计或网络硬件,这篇文章可以直接收藏备用。

我们将从硬件选型开始,因为这是成本控制的关键。然后,会详细说明在Linux系统下的驱动编译、内核模块加载以及网络配置的全过程。最后,通过实际的网络带宽测试和协议分析,来验证这块“自制”25G网卡的性能表现。整个流程侧重于可操作性,你会看到具体的命令、配置文件和排查问题的思路。

1. 核心能力速览

在深入细节之前,我们先通过一个表格快速了解这个方案的核心信息。这能帮助你判断它是否适合你的需求。

能力项说明
项目本质基于开源FPGA代码,将具备高速收发器(如GTH/GTY)的FPGA开发板实现为25G以太网网卡。
核心成本~300元人民币。主要花费在FPGA开发板(如Artix-7系列带GTH的板卡)和必要的接口转换子板(如SFP+光模块或DAC线缆接口)。
开源协议栈通常包含MAC层、PCS/PMA(物理编码子层/物理介质接入层)的FPGA逻辑代码,以及运行在主机上的Linux内核驱动。
硬件门槛需要一块带有高速收发器(支持10G/25G速率)的FPGA开发板。对用户的数字电路、FPGA开发(Verilog/VHDL)和Linux内核驱动有基础要求。
软件环境Linux操作系统(如Ubuntu 20.04/22.04),需要安装FPGA开发工具(如Vivado)、编译器、以及内核头文件用于驱动编译。
主要功能实现一个标准的网络接口,支持ifconfig、ip命令配置,能够进行网络通信。可作为学习高速接口、协议栈、网络卸载或定制化网络功能的平台。
性能目标在硬件条件满足的情况下,理论链路速率可达25Gbps。实际吞吐量受FPGA逻辑设计、驱动效率和主机PCIe带宽影响。
适合场景1.教育与学习:深入理解以太网MAC/PHY、PCIe协议、DMA数据传输。
2.研究与原型验证:为特定应用(如高频交易、网络功能虚拟化NFV、数据采集)定制网络硬件功能。
3.低成本测试环境:搭建需要多端口或特殊速率网络的测试床,而无需购买昂贵商用网卡。
不适合场景1. 追求即插即用、稳定生产环境的用户。
2. 对硬件开发毫无经验,希望获得与商用网卡完全相同体验的用户。
3. 需要官方长期驱动支持和保修的服务场景。

2. 适用场景与使用边界

这个300元25G-FPGA网卡方案,其价值在于“可定制性”和“学习深度”,而非“开箱即用”的便利性。明确它的边界,能帮助你做出正确的选择。

它非常适合以下几类人:

  • FPGA/嵌入式学习者:想要超越LED和串口,实战高速SerDes(串行解串器)、PCIe接口和DMA设计。
  • 网络协议研究者:需要在硬件层面修改或监控网络报文,例如实现自定义的拥塞控制算法、网络探测功能。
  • 高性能计算或数据中心爱好者:想搭建家庭实验室,了解RDMA(远程直接内存访问)、智能网卡(SmartNIC)的底层原理。
  • 预算有限的硬件创客:有一个需要高速网络接口的项目原型,但商用25G网卡价格高昂。

它能解决的核心问题:

  1. 降低高速硬件开发门槛:提供了一个从零到一实现网卡功能的完整参考设计。
  2. 提供可修改的代码:所有逻辑和驱动开源,你可以修改MAC地址过滤规则、增加时间戳功能、甚至集成简单的防火墙逻辑。
  3. 连接理论与实际:将《计算机网络》课本里的协议层,与FPGA中的硬件模块、Linux内核中的net_device结构体一一对应起来。

你需要警惕的局限:

  1. 稳定性与性能:开源驱动和FPGA逻辑的成熟度通常不及Intel、Mellanox等大厂的商业产品。可能遇到驱动崩溃、性能不达预期等问题。
  2. 功能完整性:可能不支持某些高级功能,如硬件卸载(TSO、LRO)、SR-IOV虚拟化、或某些网络管理协议。
  3. 生态与支持:遇到问题时,依赖社区论坛和开源Issue,响应速度和解决方案的确定性不如商业技术支持。
  4. 合规与安全:自定义的网络设备用于接入生产网络前,必须进行严格的安全和合规性评估,避免成为网络漏洞。

重要合规提醒: 使用自制网卡接入任何网络(尤其是公司或公共网络)时,必须确保其行为符合该网络的安全策略。自制设备可能缺乏商业设备的安全认证和防护机制,需自行承担安全责任。在测试环境中,建议使用独立的网络或虚拟网络进行验证。

3. 环境准备与前置条件

动手之前,请确保你已准备好以下软硬件环境。这是项目能否成功启动的基础。

3.1 硬件准备清单

  • FPGA开发板(核心):需要选择带有高速收发器(GTH或GTY)的板卡。例如:
    • Xilinx Artix-7系列:如A7-100TA7-200T,搭载GTH收发器。这是成本控制的关键,一些国产二手工况良好的板卡价格可能在200-400元。
    • 关键检查点:确认开发板手册,其高速收发器通道是否支持10.3125 Gbps25.78125 Gbps速率(对应10G/25G以太网),以及是否引出了PCIe x1/x4/x8接口。
  • 接口子板/模块
    • SFP+光模块:如果需要连接光纤网络,需要购买对应的25G SFP+光模块和光纤跳线。注意:光模块需要与FPGA板上的接口电平(通常是3.3V)兼容。
    • SFP+ DAC直连线缆:用于短距离(通常3米内)直接连接两台设备,成本低于光模块+光纤的组合,是实验室对连测试的优选。
    • 评估板自带接口:有些FPGA开发板可能直接集成了SFP+笼子。
  • 主机平台:一台带有PCIe插槽的x86电脑(台式机为宜),用于安装FPGA开发板。确保主板有可用的PCIe x4或x8插槽(物理尺寸兼容x16插槽)。
  • 调试与下载线:如Xilinx Platform Cable USB II或兼容的JTAG下载器,用于将比特流文件烧录到FPGA。

3.2 软件环境准备

  • 操作系统:推荐Ubuntu 20.04 LTS22.04 LTS。长期支持版本拥有较好的内核和驱动兼容性。需要安装build-essential,linux-headers-$(uname -r)等编译工具。
  • FPGA开发工具Xilinx Vivado(如2019.1或2020.1版本)。注意:Vivado HLx版本体积巨大(约50GB+),请提前准备好磁盘空间和许可证(WebPACK免费版通常支持Artix-7系列)。安装后确保能正常创建工程并生成比特流。
  • Git:用于克隆开源项目代码库。
  • 必要的库文件:如libelf-dev,libssl-dev等,在编译内核驱动时可能会用到。可以通过以下命令安装:
    sudo apt update sudo apt install build-essential git libelf-dev libssl-dev flex bison

4. 安装部署与启动方式

整个流程分为三个主要阶段:获取开源代码、FPGA逻辑综合与实现、Linux驱动编译与加载。我们以假设一个典型的开源FPGA网卡项目(例如基于Xilinx的cmac_usplus或类似开源MAC IP的工程)为例,描述通用流程。

4.1 获取开源项目代码首先,从代码托管平台(如GitHub)克隆项目。你需要寻找关键词如“FPGA Ethernet”、“Open Source NIC”、“Xilinx 25G”的项目。

git clone https://github.com/your-repo/open-fpga-nic.git cd open-fpga-nic

项目目录通常包含:

  • fpga/:Vivado工程文件、约束文件(XDC)、源代码(Verilog/VHDL)。
  • driver/:Linux内核驱动源代码(.c文件)和Makefile。
  • software/:可能包含用户空间工具、测试程序。
  • doc/:说明文档。

4.2 FPGA逻辑生成与烧录

  1. 打开Vivado工程:进入fpga/目录,找到.xpr工程文件,用Vivado打开。
  2. 检查与配置
    • 确认顶层模块和引脚约束(XDC文件)与你的开发板匹配。这是最容易出错的地方。你需要根据自己板卡的原理图,核对PCIe引脚、时钟引脚、SFP+收发器引脚的定义。
    • 在IP Integrator中,检查例如xxv_ethernetdma等IP核的配置,特别是链路速率(Lane Rate)设置为10.312525.78125Gbps。
  3. 综合与实现:点击Generate Bitstream。这个过程耗时较长(可能数小时),取决于电脑性能和设计复杂度。
  4. 下载比特流
    • 将FPGA板通过JTAG连接到主机。
    • 在Vivado中打开Hardware Manager,自动识别设备。
    • 将生成的.bit文件下载(Program)到FPGA中。此时,FPGA硬件层面已经具备了网卡的功能逻辑。

4.3 Linux驱动编译与加载FPGA配置好后,需要在主机操作系统上安装驱动,内核才能识别这个新设备。

  1. 进入驱动目录
    cd /path/to/open-fpga-nic/driver
  2. 编译驱动:通常使用项目提供的Makefile。你需要指定当前运行内核的构建路径。
    make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
    如果成功,会生成一个或多个.ko文件(内核模块),例如fpga_nic.ko
  3. 加载驱动模块
    sudo insmod fpga_nic.ko
  4. 检查设备是否被识别
    • 使用dmesg | tail查看内核日志,应该能看到驱动初始化的信息,如“FPGA NIC probed”、“PCI device xxxx:xxxx found”。
    • 使用lspci -v命令,在列表中找到你的FPGA设备(可能显示为“Ethernet controller”或“Unknown device”),并确认其驱动名称是fpga_nic
    • 使用ip link showifconfig -a,此时应该能看到一个新的网络接口,例如enp3s0f0eth1。它的名字可能不直观,但状态应该是DOWN

5. 功能测试与效果验证

驱动加载成功后,最关键的一步是验证网卡是否能正常工作。我们从最基本的链路激活开始,逐步测试网络功能。

5.1 基础链路与IP配置测试

  • 测试目的:验证物理链路是否连通,并为网卡配置IP地址,实现最基本的网络通信。
  • 操作步骤
    1. 连接线缆:使用SFP+ DAC线缆或通过交换机,将FPGA网卡与另一台正常工作的主机(或交换机端口)连接。
    2. 查看链路状态:执行sudo ethtool <interface_name>(例如sudo ethtool enp3s0f0)。在输出中寻找Link detected: yes。如果显示no,检查物理连接、光模块兼容性以及FPGA逻辑中的PMA/PCS状态。
    3. 启用接口并配置IP
      sudo ip link set <interface_name> up sudo ip addr add 192.168.1.100/24 dev <interface_name>
    4. 测试本地连通性:在同一子网内,从对端主机(IP如192.168.1.101)ping这个FPGA网卡。
      # 在对端主机执行 ping 192.168.1.100
  • 预期结果与判断
    • 成功:ping命令收到回复,延迟稳定。ethtool显示正确的链路速率(如Speed: 25000Mb/s)。
    • 失败
      • 链路不通ethtool显示Link detected: no。排查:线缆、光模块、FPGA比特流是否正确加载、收发器参考时钟是否正常。
      • ping不通但链路通:检查防火墙规则(sudo iptables -L)、IP配置是否正确、对端主机设置。

5.2 网络性能带宽测试

  • 测试目的:评估这块FPGA网卡的实际数据吞吐能力。
  • 操作步骤
    1. 安装测试工具:在对端主机(建议是一台性能较好的机器,配备商用高速网卡)上安装iperf3
      sudo apt install iperf3
    2. 启动iperf3服务器端(在对端主机):
      iperf3 -s
    3. 启动iperf3客户端(在FPGA网卡所在主机):
      iperf3 -c 192.168.1.101 -t 30 -P 4
      -t 30表示测试30秒,-P 4表示使用4个并行线程,有助于打满带宽。
  • 预期结果与判断
    • 成功:测试结束后,iperf3会输出带宽报告。在25G链路下,考虑到协议开销和FPGA/DMA效率,能达到15-20 Gbps的吞吐量已经是非常不错的结果。
    • 失败/性能低下
      • 带宽远低于预期(如只有1-2 Gbps):可能瓶颈在主机PCIe带宽(检查FPGA板是否插在PCIe x4或更高通道的插槽)、驱动DMA效率、或FPGA内部的数据通路设计。
      • 测试中断或有大量重传:可能表明链路不稳定或FPGA逻辑/驱动存在丢包问题。结合ethtool -S <interface_name>查看详细的统计信息(如收发包数、错误计数)。

5.3 协议与压力测试

  • 测试目的:验证网卡在复杂网络环境下的稳定性和协议兼容性。
  • 操作步骤
    1. TCP/UDP大数据量传输:使用scprsync传输一个大文件(如数GB的镜像文件),观察速度和稳定性。
    2. 使用netperf进行更全面的测试netperf可以测试TCP_RR(请求/响应)、TCP_STREAM(流)等多种模式。
    3. 网络抓包分析:使用tcpdump在FPGA网卡接口上抓包,确认报文结构正确无误。
      sudo tcpdump -i <interface_name> -w capture.pcap
      然后用Wireshark打开capture.pcap,检查以太网帧、IP头、TCP/UDP头是否正常。

6. 资源占用与性能观察

对于FPGA方案,资源占用主要分两部分:FPGA内部的逻辑资源占用,以及主机系统的CPU和内存占用。

6.1 FPGA逻辑资源占用观察这是在Vivado综合实现后就需要关注的重点。打开Vivado工程,实现(Implementation)完成后,查看“Project Summary”或“Report Utilization”。

  • 关键资源
    • LUTs(查找表):实现组合逻辑和寄存器的主要资源。一个25G以太网MAC+PCIe DMA的设计可能会消耗数万甚至十几万个LUT。
    • FFs(触发器):时序逻辑寄存器。
    • BRAMs(块RAM):用于数据缓冲、描述符队列等。占用大小取决于设计的FIFO深度。
    • DSPs(数字信号处理器):如果设计包含编解码或加密功能可能会用到。
    • GTs(高速收发器):确认你使用的收发器通道数量和位置是否与约束文件一致。
  • 判断标准:资源利用率最好在70%-80%以下,为后续功能迭代留有余地。超过90%可能导致布线困难、时序难以收敛(无法达到要求的时钟频率)。

6.2 主机系统资源占用观察当网卡驱动加载并运行后,可以在主机上观察。

  • CPU占用:使用tophtop命令。在进行iperf3带宽测试时,观察%CPU使用率。一个高效的驱动应能将大部分数据搬运工作卸载给DMA,CPU占用率不会极高。如果CPU占用率接近100%,可能是驱动的中断处理或数据拷贝路径不够优化。
  • 内存占用:驱动本身占用内存不大,但会通过DMA与主机交换数据。主要观察在高速数据传输时,系统内存是否稳定。
  • 中断观察:使用cat /proc/interrupts | grep fpga_nic(假设驱动名称为fpga_nic)可以查看该网卡产生的中断数量。在流量通过时,中断数应平稳增长。

6.3 性能调优初步思路如果测试性能不理想,可以从以下方面排查:

  1. PCIe带宽:使用lspci -vv命令查看FPGA设备所在的PCIe链路速度和宽度(LnkSta)。确保是Speed 8GT/s(PCIe 3.0)或更高,并且宽度是x4x8
  2. 驱动参数:有些开源驱动支持模块参数。在加载驱动时可以通过sudo insmod fpga_nic.ko param=value的方式调整,例如调整DMA描述符环的大小、中断合并参数等。具体参数需查阅驱动代码或文档。
  3. 内核参数:调整网络栈参数,如net.core.rmem_max,net.core.wmem_max,增加Socket缓冲区大小。
    sudo sysctl -w net.core.rmem_max=134217728 sudo sysctl -w net.core.wmem_max=134217728

7. 常见问题与排查方法

在部署和测试过程中,你几乎一定会遇到问题。下表整理了常见的问题现象、可能原因和排查步骤。

问题现象可能原因排查方式解决方案
Vivado综合失败代码语法错误、IP核许可证缺失、约束文件错误。查看Vivado Tcl Console和Log窗口的错误信息。根据错误信息修正代码或约束。检查IP核是否使用免费WebPACK许可证支持的型号。
比特流下载后设备无反应JTAG连接不稳定、FPGA板供电不足、比特流未正确配置到Flash(如果使用)。1. 重新插拔JTAG线。
2. 检查电源指示灯。
3. 在Vivado Hardware Manager中确认编程成功。
确保供电稳定。对于需要上电启动的场景,将比特流烧录到板载Flash中。
lspci看不到设备FPGA板PCIe金手指接触不良、主板PCIe插槽禁用(BIOS设置)、FPGA逻辑中的PCIe IP核未正确配置或未生成。1. 重新插拔FPGA板,换一个PCIe插槽试试。
2. 进入主机BIOS,确保PCIe插槽已启用。
3. 检查Vivado中PCIe IP核的链路训练(LTSSM)状态。
清洁金手指。在BIOS中恢复默认设置或手动启用PCIe。在Vivado中利用ILA(集成逻辑分析仪)抓取PCIe核的LTSSM状态信号进行调试。
驱动编译错误内核头文件不匹配、缺少依赖库、代码不兼容当前内核版本。查看make命令输出的具体错误信息。1. 确认已安装linux-headers-$(uname -r)
2. 根据错误安装缺失的包(如libelf-dev)。
3. 尝试在驱动Makefile中为老内核添加兼容性宏(如CONFIG_COMPAT)。
insmod加载驱动失败驱动与当前内核版本不兼容、符号未找到、依赖其他模块。使用`dmesgtail`查看内核输出的详细错误。
ethtool显示Link detected: no物理线缆/光模块问题、FPGA收发器参考时钟未就绪、PCS/PMA逻辑未锁定、对端设备未启动或速率不匹配。1. 更换线缆或光模块测试。
2. 在Vivado ILA中抓取收发器的rxstatuscplllock等信号。
3. 确认对端设备端口已启用并协商到相同速率。
1. 使用示波器测量参考时钟。
2. 检查FPGA约束文件中时钟引脚和电平标准是否正确。
3. 强制双方端口速率和双工模式(sudo ethtool -s <interface> speed 25000 duplex full autoneg off)。
iperf3测试带宽极低PCIe带宽瓶颈(如运行在x1模式)、驱动DMA效率低、FPGA内部数据通路阻塞、主机CPU性能不足或中断处理瓶颈。1.lspci -vv检查PCIe链路速度和宽度。
2.top观察iperf3进程和内核中断的CPU占用。
3. 使用perf工具进行性能剖析。
1. 确保FPGA板插在正确的插槽(x4或x8)。
2. 尝试调整驱动模块参数(如中断合并阈值、描述符数量)。
3. 优化FPGA逻辑的数据流,避免背压。
网络传输大量丢包DMA描述符环溢出、接收缓冲区不足、物理链路误码率高。1.ethtool -S <interface>查看rx_missed_errors,rx_over_errors等统计。
2.ethtool --show-priv-flags <interface>(如果驱动支持)查看内部状态。
1. 增加驱动中接收描述符环的大小。
2. 调整内核网络参数(rmem_max,wmem_max)。
3. 检查光纤连接器是否清洁,线缆是否过长。
系统不稳定或死机DMA操作错误(如访问非法内存地址)、驱动存在内核恐慌(panic)、FPGA逻辑故障导致总线挂死。分析内核崩溃日志(/var/log/kern.logdmesg)。1. 检查驱动代码中的内存映射和DMA地址操作。
2. 在FPGA逻辑中增加超时和错误恢复机制。
3. 使用更保守的时钟频率和时序约束重新综合FPGA设计。

8. 最佳实践与使用建议

为了让你在探索这个低成本FPGA网卡方案时更顺利,这里有一些从经验中总结的建议。

8.1 起步阶段:最小系统验证不要一开始就追求完美性能和全部功能。你的第一个目标应该是让系统“跑通”。

  1. 降低速率:如果25G链路调试困难,可以先尝试将FPGA逻辑和对方交换机/网卡协商到10G1G模式。这能排除高速信号完整性问题。
  2. 简化逻辑:在开源项目中,先注释掉可能的高级功能(如统计计数器、多队列),只保留最简MAC+PCIe DMA数据通路进行验证。
  3. 使用环回测试:在FPGA逻辑内部实现MAC层的环回(Loopback),不依赖外部物理链路,先验证驱动和DMA路径是否正常。

8.2 开发与调试技巧

  1. 版本控制:使用Git管理你对FPGA代码和驱动代码的所有修改。每次重大修改前做一个提交,便于回退。
  2. 充分利用ILA:Vivado的ILA(集成逻辑分析仪)是你的“数字示波器”。在关键信号(如AXI-Stream接口的tvalid/tready、PCIe的TLP包信号、MAC的rxd/txd)上插入ILA核,可以直观看到数据流和状态机跳转,是定位硬件逻辑问题的利器。
  3. 驱动调试输出:在驱动代码中合理使用printk(注意日志级别,如KERN_INFO,KERN_DEBUG),并通过dmesg观察。可以输出DMA描述符状态、中断次数、收发包计数等关键信息。
  4. 分而治之:将问题隔离。先用标准测试工具(如ping,iperf)在主机端测试,再用逻辑分析仪/ILA在FPGA端测试,最后将两者对接。

8.3 项目管理与安全

  1. 文档记录:详细记录你的硬件型号、FPGA芯片型号、引脚约束、软件版本、遇到的错误和解决方法。这能为你节省大量未来回头排查的时间。
  2. 环境隔离:建议使用一台专用的测试主机,避免因驱动或内核问题影响你的日常工作电脑。
  3. 网络隔离:在彻底稳定和了解其网络行为前,切勿将自制的FPGA网卡接入公司内网或公共互联网。应在独立的交换机或直接点对点连接的环境中进行测试。
  4. 合规使用:确保你的使用符合无线电管理规定(如果涉及无线)和网络安全管理条例。用于学习和研究目的通常没有问题,但用于商业部署前务必进行全面的评估。

通过这个低成本FPGA网卡项目,你获得的远不止一块能用的网卡。你深入接触了从高速串行收发器、数字逻辑设计、PCIe协议、DMA引擎到Linux内核网络驱动栈的完整链条。每一个问题的解决,都是对“计算机是如何工作的”这个宏大命题的一次深刻理解。先从让链路灯亮起、让ping包通起来开始,逐步挑战更高的性能和更复杂的功能,这个过程本身就是硬件开发者最好的成长路径。

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

推荐系统引入好奇心机制:打破信息茧房的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:13:55

Windows平台SOEM控制禾川伺服:从环境搭建到使能状态机全链路实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:10:39

软件测试效率低?从用例设计到自动化选型的6个改进方向

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:10:30

基于OCR与图像识别的游戏阵容自动化分析工具实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 19:10:12

红米AX5400频繁死机断网?电容老化检测与更换维修实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华