From d231b3d8e31a14518f8c91d59030b321b1e70d02 Mon Sep 17 00:00:00 2001 From: wangxujun 02605 Date: Wed, 9 Sep 2026 14:34:51 +0800 Subject: [PATCH] docs: publish day01 note + 3 kb cards (2026-09) Co-Authored-By: Claude --- kb/2026-09.md | 21 ++++---- notes/index.md | 2 +- notes/phase0/day01-pcie-topology.md | 83 +++++++++++++++++------------ 3 files changed, 62 insertions(+), 44 deletions(-) diff --git a/kb/2026-09.md b/kb/2026-09.md index f449ae9..10daedd 100644 --- a/kb/2026-09.md +++ b/kb/2026-09.md @@ -1,15 +1,16 @@ # 2026-09 -## 09-09 P0-PCIe 拓扑与 Config Space -- 读: Day01 讲义(融合版,X540 / uNOS M0 锚点)+ lspci 命令用法 -- 写: Day01-lecture.md 重写 + Day01 笔记(重跑版) -- 数据: BDF 地址空间 256×32×8 = 65536;Config Space 256B,前 16B 全行业统一;MSI-X 32 向量 +## 09-09 P0-Day01 PCIe 拓扑与 Config Space +- 读: Day01-lecture.md(拓扑/BDF/Config Space/BAR) +- 写: 无(概念日) +- 数据: BDF 上限 256×32×8 = 65536 功能;Config Space 256B;X540 ID 以 lspci 实测为准 ## 09-09 算法-哈希表原理 -- 读: 自写理论 `algo-theory/01-hash-table.md` -- 写: LC1 参考实现(未独立完成 🔴,09-11 重做) -- 数据: 平均 O(1) 最坏 O(n);负载因子 α>0.75 扩容 rehash +- 读: algo-theory/01-hash-table.md + LC1 参考实现 +- 写: 无(🔴 要求参考实现,09-11 重做) +- 数据: 平均 O(1) 最坏 O(n);负载因子 >0.75 扩容 rehash -## 09-09 做了-LC1 先查后存坑 -- 坑: 先存后查 → [3,3] 把自己匹配掉(同一元素用两次) -- → 修复: 先查后存,"只向过去提问";表里只有历史没有自己 +## 09-09 RDMA-丢包的代价 +- 读: Week 1 开篇(QP/verbs/零拷贝/RoCEv2) +- 写: 无 +- 数据: 丢包 = 全局传染 + ≥1 RTT 硬件重传 + 木桶放大;PFC 暂停 = 局部可恢复 diff --git a/notes/index.md b/notes/index.md index b457cc8..e47df59 100644 --- a/notes/index.md +++ b/notes/index.md @@ -6,7 +6,7 @@ | Day | 主题 | 日期 | |-----|------|------| -| [Day 01](/notes/phase0/day01-pcie-topology) | PCIe 拓扑结构 | Sep 2026(重跑版) | +| [Day 01](/notes/phase0/day01-pcie-topology) | PCIe 拓扑结构 | Sep 2026(重启后 Day 1) | | [Day 02](/notes/phase0/day02-kernel-rx-path) | 内核收包路径分析 | Jun 2026 | | [Day 03](/notes/phase0/day03-kernel-memory) | 内核内存管理 | Jun 2026 | | [Day 04](/notes/phase0/day04-rcu-lockfree) | RCU & Lock-free 编程 | Jun 2026 | diff --git a/notes/phase0/day01-pcie-topology.md b/notes/phase0/day01-pcie-topology.md index c6fe181..7ea1f93 100755 --- a/notes/phase0/day01-pcie-topology.md +++ b/notes/phase0/day01-pcie-topology.md @@ -1,47 +1,64 @@ -# Phase 0 · Day 01: PCIe 总线拓扑与 Config Space(2026-09-09 重跑版) +# Phase 0 · Day 01: PCIe 总线拓扑与 Config Space -> 融合锚点: uNOS M0 骨架(找到 X540 网卡)+ X540-T2 硬件 -> 配套讲义: `notes/Phase0/Day01-lecture.md`(融合版,X540 + uNOS M0 视角) +> 2026-09-09(主线 Day 1 · 重启后) | 讲义: `Day01-lecture.md` | 融合锚点: uNOS M0 + X540-T2 ---- +## 一、核心图景:软件怎么碰到硬件 -## 一、主线:PCIe 四件套 +DPDK/uNOS 的第一行代码 `rte_eal_init()` 返回之前要完成:扫 PCIe 树 → 按 Vendor/Device ID 认出 X540 → 读 Config Space 拿 BAR → 映射成用户态可写地址(MMIO)→ 之后 PMD 写寄存器 = 收发包。**PCIe 就是"软件碰到硬件"的那条路**,也是 P4 手写驱动的同一块知识。 -| 概念 | 一句话 | 你的类比 | +## 二、拓扑:一条树,三个角色 + +``` +CPU(Root Complex) → Root Port(桥, 引出新总线) → X540(Endpoint) +``` + +- Root Complex = CPU 访问 PCIe 的唯一入口;Bridge 扩展总线;Endpoint = 设备本身 +- 类比: 机框/板卡/端口 三级编号 = Bus/Device/Function + +## 三、BDF:设备的身份证 + +| 字段 | 位数/范围 | 含义 | |---|---|---| -| 拓扑 | CPU(Root Complex)→ Root Port → Endpoint 的树 | 机框 → 板卡 → 端口 | -| BDF | Bus:Device.Function,256×32×8 = 65536 个功能 | 端口门牌号 | -| Config Space | 256B 出厂说明书,前 16B 全行业统一(Vendor/Device ID 驱动匹配依据) | show version 板卡信息 | -| BAR + MMIO | 寄存器映射进 CPU 地址空间,读写地址 = 操作网卡 | asic_write_register 的物理本质 | -| MSI-X | 32 向量 = 多队列并行收包的硬件基础 | uNOS 未来扩核直接复用 | +| Bus | 0~255 | 第几条总线 | +| Device | 0~31 | 同总线第几个设备 | +| Function | 0~7 | 芯片的独立功能 | -**落点**: `rte_eal_init()` = 扫树 → 匹配 X540 ID → 读 BAR/MSI-X → vfio 绑定。M0 验收 `eth_dev_count()=1` 就是这条链路的结果。 +全系统最多 65536 个功能。DPDK 绑卡 `dpdk-devbind.py -b vfio-pci 03:00.0` 报的就是 BDF。 -## 二、算法:哈希表 + LC1(🔴 待重做) +## 四、Config Space:出厂说明书(256B) -- 哈希三组件:哈希函数 h(key)、桶数组、冲突处理(链地址法 / 开放寻址;DPDK rte_hash = cuckoo) -- 负载因子 α > 0.75 → 扩容 rehash;平均 O(1),最坏 O(n) -- **核心不变量:先查后存,只向过去提问**——表里只有历史,没有自己,天然排除自我匹配 -- LC1 参考实现已给(`job-search/algo-code/lc1-two-sum-ref.cpp`),**重做日 09-11**(重做前别看 ref) -- 产品锚点:conntrack 表 = 五元组哈希;flow cache 的 hash_key 在你自己的 uNOS 设计文档里就写着 +| Byte | 字段 | 含义 | +|---|---|---| +| 0-1 | Vendor ID | 0x8086 = Intel | +| 2-3 | Device ID | **驱动匹配第一依据** | +| 9-11 | Class Code | 0x020000 = 网络控制器 | +| 14 | Header Type | 0x00 = Endpoint | -## 三、踩坑节(今天真实的两个坑) +## 五、BAR + MMIO:CPU 碰网卡的物理通道 -### 坑 1:C++ 语法不熟导致无法起手 -- **现象**: 哈希原理讲完仍写不出代码,自己起手时把 map 声明成了 class 成员 -- **定位**: 词汇量不足(知道"要说什么",不会"怎么说"),不是算法不懂 -- **修复**: TODO 脚手架模式 + 参考实现逐段讲解 + 09-11 重做;语法文档 §3/§5 当字典随用随查 +- BAR = 网卡向 OS 要的一段物理地址,映射自己的寄存器;CPU 读写 = 操作网卡 +- 本质即交换机 SDK 的 `asic_write_register(addr, val)` 同款操作 +- MSI-X 32 向量 = 多队列并行的硬件基础(uNOS 单核现在用 1,扩核复用) -### 坑 2:"先存后查"自我匹配 -- **现象**: 先存自己再查,`[3,3]` 会查到刚存的自己 -- **根因**: 查表时自己已在表里,违反"同一元素不能用两次" -- **修复**: 先查后存——查表那一刻表里只有"我之前的元素" +## 六、算法穿插:哈希表 + LC1 -## 四、检验标准 +- 哈希 = 把"值"换算成"下标",借数组 O(1) 给查找;三组件:哈希函数/桶数组/冲突处理 +- LC1 两数之和:一趟遍历,每步问"补数出现过吗"(存在性查询 O(1)),先查后存保证"只向过去提问" +- **评级 🔴**:要求参考实现,未独立完成 → **09-11 重做** +- 产品锚点: conntrack 表(M2)/ flow cache(M1, rte_hash)就是哈希表的工业形态 + +## 七、冲刺穿插:RDMA 开篇 + +- RDMA = 网卡直接搬数据,CPU 不参与(QP/verbs、注册内存零拷贝、硬件可靠传输) +- RoCEv2 = 以太网上的 RDMA → 对丢包零容忍 → 无损以太网成为 Week 1 主题 +- **丢包 vs 暂停的代价账**:丢包 = 全局/传染/触发 ≥1 RTT 硬件重传 + AllReduce 木桶放大;PFC 暂停 = 局部/可恢复 → 宁可暂停不可丢包 + +## 检验标准 - [ ] 能画出 CPU → RC → Root Port → X540 拓扑并解释三角色 -- [ ] 能说出 Config Space 驱动匹配靠 Vendor/Device ID -- [ ] 能讲清 rte_eal_init 找到网卡的步骤链 -- [ ] 能口述哈希表三组件 + 负载因子的作用 -- [ ] 能讲清"先查后存,只向过去提问"的不变量 -- [ ] 09-11 重做 LC1:独立写出来(不看 ref) +- [ ] 能解释 BDF 三字段与 65536 上限 +- [ ] 能说出驱动匹配靠 Config Space 哪两个字段 +- [ ] 能解释 BAR+MMIO 并联系 asic_write_register +- [ ] 能讲清 rte_eal_init 找 X540 的五步 +- [ ] 能口述哈希表"先查后存"为什么防自我匹配 +- [ ] 能说出 RDMA 丢包三层代价(重传 RTT/木桶/传染)