eBPF 运行时架构:Verifier、JIT、Map 与加载流程

eBPF 运行时架构:Verifier、JIT、Map 与加载流程

要把一段 C 写的逻辑安全地跑进 Linux 内核,靠的不是「信任开发者」,而是一套固定流水线:编译 → 加载 → 校验 →(可选)JIT → 挂接事件 → 经 Map/ringbuf 回传用户态 。本文把这条链路拆开说明,并补充指令架构与 bpf() 系统调用要点,便于独立理解 eBPF 运行时本身。

Clang/LLVM 属于 编译工具链 ;Verifier、JIT、Map、bpf() 才是 内核子系统运行时------二者不要混为一谈。


目录

  1. 整体架构一张图
  2. [开发工具链:Clang / LLVM](#开发工具链:Clang / LLVM)
  3. Verifier:安全与正确性的闸门
  4. [解释器与 JIT](#解释器与 JIT)
  5. Map:内核与用户态的数据面
  6. 程序加载与生命周期
  7. [指令架构要点(cBPF vs eBPF)](#指令架构要点(cBPF vs eBPF))
  8. [bpf 系统调用在做什么](#bpf 系统调用在做什么)
  9. 实践中的常见失败点
  10. [附录:常见 Verifier 报错速查](#附录:常见 Verifier 报错速查)

整体架构一张图

eBPF 子系统可粗分为四块:

模块 作用
开发工具链 Clang/LLVM 把 C(等)编成 eBPF 字节码,常打包为 ELF
Verifier 加载前静态分析:访问、边界、类型、控制流等
JIT Compiler 把字节码译为本机指令,降低解释开销
Map / 辅助结构 跨调用存状态;用户态与内核态交换数据

#mermaid-svg-iqrpv11a121Otlz9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iqrpv11a121Otlz9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iqrpv11a121Otlz9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iqrpv11a121Otlz9 .error-icon{fill:#552222;}#mermaid-svg-iqrpv11a121Otlz9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iqrpv11a121Otlz9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iqrpv11a121Otlz9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iqrpv11a121Otlz9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iqrpv11a121Otlz9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iqrpv11a121Otlz9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iqrpv11a121Otlz9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iqrpv11a121Otlz9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iqrpv11a121Otlz9 .marker.cross{stroke:#333333;}#mermaid-svg-iqrpv11a121Otlz9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iqrpv11a121Otlz9 p{margin:0;}#mermaid-svg-iqrpv11a121Otlz9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iqrpv11a121Otlz9 .cluster-label text{fill:#333;}#mermaid-svg-iqrpv11a121Otlz9 .cluster-label span{color:#333;}#mermaid-svg-iqrpv11a121Otlz9 .cluster-label span p{background-color:transparent;}#mermaid-svg-iqrpv11a121Otlz9 .label text,#mermaid-svg-iqrpv11a121Otlz9 span{fill:#333;color:#333;}#mermaid-svg-iqrpv11a121Otlz9 .node rect,#mermaid-svg-iqrpv11a121Otlz9 .node circle,#mermaid-svg-iqrpv11a121Otlz9 .node ellipse,#mermaid-svg-iqrpv11a121Otlz9 .node polygon,#mermaid-svg-iqrpv11a121Otlz9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iqrpv11a121Otlz9 .rough-node .label text,#mermaid-svg-iqrpv11a121Otlz9 .node .label text,#mermaid-svg-iqrpv11a121Otlz9 .image-shape .label,#mermaid-svg-iqrpv11a121Otlz9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-iqrpv11a121Otlz9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iqrpv11a121Otlz9 .rough-node .label,#mermaid-svg-iqrpv11a121Otlz9 .node .label,#mermaid-svg-iqrpv11a121Otlz9 .image-shape .label,#mermaid-svg-iqrpv11a121Otlz9 .icon-shape .label{text-align:center;}#mermaid-svg-iqrpv11a121Otlz9 .node.clickable{cursor:pointer;}#mermaid-svg-iqrpv11a121Otlz9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iqrpv11a121Otlz9 .arrowheadPath{fill:#333333;}#mermaid-svg-iqrpv11a121Otlz9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iqrpv11a121Otlz9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iqrpv11a121Otlz9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iqrpv11a121Otlz9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iqrpv11a121Otlz9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iqrpv11a121Otlz9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iqrpv11a121Otlz9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iqrpv11a121Otlz9 .cluster text{fill:#333;}#mermaid-svg-iqrpv11a121Otlz9 .cluster span{color:#333;}#mermaid-svg-iqrpv11a121Otlz9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iqrpv11a121Otlz9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iqrpv11a121Otlz9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-iqrpv11a121Otlz9 .icon-shape,#mermaid-svg-iqrpv11a121Otlz9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iqrpv11a121Otlz9 .icon-shape p,#mermaid-svg-iqrpv11a121Otlz9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iqrpv11a121Otlz9 .icon-shape .label rect,#mermaid-svg-iqrpv11a121Otlz9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iqrpv11a121Otlz9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iqrpv11a121Otlz9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iqrpv11a121Otlz9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
C 源码
Clang/LLVM
含 eBPF 的 ELF
libbpf / bpftool / Agent
bpf() 系统调用
Verifier
JIT / Interpreter
挂到 hook 上执行
Maps / ringbuf
用户态消费

用户态「加载器」可以是 libbpf 链接进你的进程,也可以是 bpftool ,或 Cilium Agent 一类长期守护进程------最终都落到 bpf()


开发工具链:Clang / LLVM

现代写法几乎总是:

  1. 受限的 C(或通过框架生成)编写内核侧程序
  2. Clang 目标设为 bpf,产出目标文件
  3. libbpf (或其他加载器)解析 ELF section、重定位、BTF,再调用 bpf() 装入内核

内核侧程序通常短小、无libc、不能随意调用内核函数,只能使用 白名单辅助函数(helpers) 与 Map 操作。用户态程序负责:打开对象、挂 pin、轮询 ringbuf、设置挂载点、处理权限。

BTF(BPF Type Format)CO-RE(Compile Once -- Run Everywhere) 让同一份字节码在不同内核版本上通过类型重定位适配结构体布局,是生产级探针可移植性的关键基础设施。


Verifier:安全与正确性的闸门

Verifier 在程序进入内核执行路径前做静态检查,目标包括:

检查类 含义(直观)
访问控制 指针是否来自合法上下文;禁止任意内核地址乱读
边界检查 包数据、栈、Map 值访问是否在已知范围内
控制流 循环须可证明有界;禁止无法证明终止的路径
类型 / 状态机 寄存器状态是否一致;helper 参数是否合法
复杂度 指令数、分支探索有上限,过复杂会被拒

未通过校验的程序 不会 被挂上 hook。这是 eBPF 相对「任意内核模块」的核心差异:表达力换安全边界。

它怎么查:CFG 与路径探索

Verifier 会对程序建 控制流图(CFG),再做路径上的抽象解释(寄存器/栈状态一路推进)。实现上接近对分支做深度优先式探索,并对等价状态做剪枝,以免路径爆炸。

为兼顾安全与分析时间,内核限制了 最大指令数、最大探索状态/路径规模 等。因此:

复杂循环常被拒绝------未必是逻辑写错了 ,而是 Verifier 无法在限定步数内证明循环终止或各路径状态一致。过深的分支嵌套也会被当成对校验器本身的 DoS 风险而拒绝。

调试技巧:加载失败时务必打开并阅读 verifier log (经 bpf() / libbpf 返回)。多数「C 能编过、内核不收」的问题,日志会指到具体指令与寄存器状态。不同框架对这份日志的暴露方式不同:libbpf 常直接打到 stderr;BCC 有时淹没在 Python 异常里------选型时这会影响排障体验。


解释器与 JIT

校验通过后,执行有两条路:

方式 优点 缺点
Interpreter 实现简单、易调试、部分环境默认可用 逐条解释,热点路径更慢
JIT 译成本地机器码,可做优化,吞吐更好 实现复杂;需架构支持与安全考虑

生产环境在 x86_64 / arm64 等上通常期望 JIT 开启 。注意:JIT 编译的是 已通过 Verifier 的程序,并不是绕过校验。


Map:内核与用户态的数据面

eBPF Map 是内核中的键值类结构,用途包括:

  • 程序多次触发之间保存计数、直方图、连接表
  • 用户态下发配置(如过滤规则)
  • 内核态向用户态导出结果(也可配合 perf event / ringbuf

常见类型(名称随内核演进):HASHARRAYLRU_HASHPERCPU_*LPM_TRIERINGBUF 等。选型时关注:

  • 并发:是否 per-CPU,是否需要原子更新
  • 容量与逐出:LRU 是否可接受丢数据
  • 读写路径:控制面更新频率 vs 数据面查询频率

内存模型与锁:为何没有「随便 mutex」

eBPF 程序常跑在 不可休眠的上下文(软中断、某些 hook 等),因此:

  • Map 更新路径 不能 使用会睡眠的常规互斥锁
  • 跨 CPU 的复合更新,在支持的内核上可用 bpf_spin_lock(以及相关 map 标志如带锁 value 布局);必须极短持锁,防死锁与长时间关抢占
  • 高频计数 优先 PERCPU_* Map:各 CPU 本地累加,用户态再汇总,减少跨核缓存行争用
text 复制代码
用户态:bpf_map_update_elem / lookup / 删除、或 ringbuf 读
内核态:bpf_map_* helpers、bpf_ringbuf_submit ...

没有 Map(或等价通道),eBPF 程序往往只能做「静默副作用」(如直接丢包),很难做成可观测流水线。


程序加载与生命周期

典型四步:

  1. 编写

    • 内核态:事件处理逻辑
    • 用户态:加载、参数、输出、卸载
  2. 编译与整理

    • Clang → ELF
    • libbpf 解析、准备 load 参数
  3. 校验与翻译

    • Verifier
    • JIT 或解释器就绪
  4. 运行与监控

    • attach 到 kprobe/tracepoint/XDP/cgroup 等
    • 用户态读 Map / ringbuf
    • 结束后 detach 并释放 fd(或依赖进程退出)

Tracepoint/kprobe/XDP 内核 eBPF 子系统 用户态加载器 Tracepoint/kprobe/XDP 内核 eBPF 子系统 用户态加载器 #mermaid-svg-rA4pRnowuR8n3zGr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rA4pRnowuR8n3zGr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rA4pRnowuR8n3zGr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rA4pRnowuR8n3zGr .error-icon{fill:#552222;}#mermaid-svg-rA4pRnowuR8n3zGr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rA4pRnowuR8n3zGr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rA4pRnowuR8n3zGr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rA4pRnowuR8n3zGr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rA4pRnowuR8n3zGr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rA4pRnowuR8n3zGr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rA4pRnowuR8n3zGr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rA4pRnowuR8n3zGr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rA4pRnowuR8n3zGr .marker.cross{stroke:#333333;}#mermaid-svg-rA4pRnowuR8n3zGr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rA4pRnowuR8n3zGr p{margin:0;}#mermaid-svg-rA4pRnowuR8n3zGr .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rA4pRnowuR8n3zGr text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-rA4pRnowuR8n3zGr .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rA4pRnowuR8n3zGr .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-rA4pRnowuR8n3zGr .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-rA4pRnowuR8n3zGr .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-rA4pRnowuR8n3zGr #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-rA4pRnowuR8n3zGr .sequenceNumber{fill:white;}#mermaid-svg-rA4pRnowuR8n3zGr #sequencenumber{fill:#333;}#mermaid-svg-rA4pRnowuR8n3zGr #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-rA4pRnowuR8n3zGr .messageText{fill:#333;stroke:none;}#mermaid-svg-rA4pRnowuR8n3zGr .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rA4pRnowuR8n3zGr .labelText,#mermaid-svg-rA4pRnowuR8n3zGr .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-rA4pRnowuR8n3zGr .loopText,#mermaid-svg-rA4pRnowuR8n3zGr .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-rA4pRnowuR8n3zGr .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-rA4pRnowuR8n3zGr .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-rA4pRnowuR8n3zGr .noteText,#mermaid-svg-rA4pRnowuR8n3zGr .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-rA4pRnowuR8n3zGr .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rA4pRnowuR8n3zGr .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rA4pRnowuR8n3zGr .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-rA4pRnowuR8n3zGr .actorPopupMenu{position:absolute;}#mermaid-svg-rA4pRnowuR8n3zGr .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-rA4pRnowuR8n3zGr .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-rA4pRnowuR8n3zGr .actor-man circle,#mermaid-svg-rA4pRnowuR8n3zGr line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-rA4pRnowuR8n3zGr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} bpf(BPF_PROG_LOAD, ...) Verifier prog_fd attach / link 注册程序 事件触发执行 Map/ringbuf 数据 detach / close

权限:最小特权,而不是默认 root

Linux 5.8 起引入 CAP_BPF,把 BPF 相关能力从粗粒度特权里拆出来。实践中常见组合:

能力 常见用途
CAP_BPF 加载程序、操作多数 Map 等(视内核与操作类型)
CAP_PERFMON 性能监控向操作;读取某些内核地址/跟踪场景常需要
CAP_SYS_ADMIN 历史兼容;权限过大,生产应尽量避免「一把梭」

容器场景还要看 seccomp、是否允许 bpf()、以及发行版对 unprivileged BPF 的默认策略。生产遵循最小权限 :能 CAP_BPF + CAP_PERFMON 就不要直接给 root。


指令架构要点(cBPF vs eBPF)

不必背完整 opcode,抓住差异即可:

维度 cBPF(经典) eBPF
定位 包过滤为主 通用程序类型
寄存器 极少(累加器等模型) 更多通用寄存器(如 10+ 模型)
调用 能力弱 可调用受控 helpers
数据 过滤结果为主 Map、栈、上下文结构
宽度 历史 32 位色彩更重 64 位友好

eBPF 程序仍是 寄存器机 + 有限指令序列;Verifier 按指令做抽象解释。写出「像普通 C」却大量依赖未建模行为,是校验失败的常见原因。

调试:把字节码和本机码对上

命令 用途
bpftool prog dump xlated 查看经内核处理后的 eBPF 指令(类伪代码),对照 Verifier 视角
bpftool prog dump jited 查看 JIT 后的本机汇编,分析热点与调用开销

先看 xlated 理解「校验器眼里的程序」,再看 jited 理解「CPU 真正在跑什么」------排查性能与异常行为时很有用。


bpf 系统调用在做什么

bpf(2) 是用户态与 eBPF 子系统的主接口。通过不同 cmd 完成例如:

能力族 示例意图
程序 加载、查询程序信息
Map 创建、查改删元素、获取 fd
链接 / 挂载 把程序关联到 cgroup、hook(具体 API 随版本演进,也常经 libbpf 封装)
BTF 加载类型信息,支撑 CO-RE
批处理 / 迭代 提高 Map 操作效率(较新内核)

日常开发更推荐经 libbpf 调用,而不是手拼每个 bpf() 参数;但理解「最终都落到系统调用」有助于排查权限、返回码与审计日志。


实践中的常见失败点

现象 常见原因
⚠️ load 失败,verifier reject 未证明的边界、循环、错误 helper 用法、栈溢出
⚠️ 能 load 不能 attach 内核缺配置、hook 类型不匹配、符号不存在
⚠️ 有程序无数据 事件未触发、PID/过滤条件过严、Map 类型用错
⚠️ 跨机无法运行 无 BTF、结构体偏移变化、未做 CO-RE
⚠️ 性能抖动 在热点用重逻辑;改用 per-CPU Map / 采样

收束 :eBPF 的「安全可编程」来自 Verifier + 有限运行时模型 ;可观测性管线的数据面几乎总是 Map/ringbuf ;用户态真正要掌握的是 加载器与生命周期,而不是背指令表。

框架如何组织编译、如何把 Verifier 日志摊到你面前(BCC 在线编译 vs libbpf 预编译 + CO-RE),会直接改变上述失败点的体感------那是开发框架选型要回答的问题。


附录:常见 Verifier 报错速查

读日志时先看 出错指令编号寄存器状态(R0--R10),再对号入座。下列为高频模式(措辞随内核版本略有出入)。

日志关键词 / 模式 常见代码原因 改法思路
invalid mem access 读指针前未做空指针/边界检查;Map lookup 返回值直接解引用;包数据偏移未对 data_end 证明 lookup 后先判 NULL;所有包访问写成 data + off <= data_end 可证明形式
R0 !read_ok / R0 invalid 返回值寄存器状态不合法;helper 失败路径未处理就当作成功指针用 检查 helper 返回值;失败路径显式 return
invalid access to map value 写出的长度超过 value size;对可变长/联合体按错误大小访问 按 map value 定义截断;用正确类型与 bpf_probe_read* 长度
misaligned access 未对齐的标量/结构体访问 按对齐读,或拆成字节拷贝到栈上再组
infinite loop detected / 循环相关拒绝 循环上界非常量或 Verifier 推不出上界 常量化趟数;展开小循环;把复杂解析放到用户态
program is too large / complexity 指令过多或分支状态爆炸 拆程序、降分支、用 map 查表代替深层 if-else
calling kernel function ... is not allowed 直接调了非 helper 的内核符号 只用白名单 helper;或换有对应 kfunc 的较新内核并正确声明
type=scalar expected=fp 一类类型错误 把标量当指针,或指针算术弄丢「指针类型」标记 避免随意 (void *) 转换;保持从 ctx/map 来的指针谱系清晰
stack ... out of bounds / 栈溢出 栈上大数组、过深内联 缩小栈对象;大缓冲改 Map;降低内联深度

最小复现习惯 :把出问题的访问缩成「lookup → 判空 → 受限长度拷贝」三步,再对照 bpftool prog dump xlated 看寄存器是否仍带「合法指针 + 已知上限」。

整理自《深入理解 eBPF 与可观测性》架构与特性相关内容,并扩展运行时、权限与 Verifier 排错视角。

相关推荐
Zsy_05100319 小时前
【Linux】笔记01:基础命令
linux·运维·服务器
我星期八休息1 天前
网络编程—应用层HTTP协议
linux·运维·开发语言·前端·网络·网络协议·http
ShineWinsu1 天前
对于Linux:UDPsocket编程基础的解析
linux·运维·网络协议·udp·ip·端口号·进程间通信
hehelm1 天前
AI大模型接入SDK—通用模块设计
linux·开发语言·c++
Ai拆代码的曹操1 天前
K8s Pod Pending 逐层排查:从 FailedScheduling 到 PVC StorageClass 不存在的实战记录
java·linux·kubernetes
wangbing11251 天前
JPA下自定义主键
java·linux·服务器
bush41 天前
正点原子imx6ull-uboot,奇怪的问题
linux·学习
dddwjzx1 天前
嵌入式Linux C应用编程——Framebuffer应用编程
linux·嵌入式
今天也想躺ping1 天前
linux系统移植pjsua库实现sip通话功能
linux·sip·交叉编译