Vcan 虚拟总线 -- 零硬件成本的实验环境

1. 为什么用 vcan?

在开始 CAN 开发之前,我们需要一个 CAN 测试环境。vcan(Virtual CAN)是 Linux 内核提供的虚拟 CAN 网络设备,它:

  • 不需要任何 CAN 硬件 —— 在纯软件环境中模拟 CAN 总线行为
  • 行为与真实 CAN 控制器一致 —— 帧收发、过滤器、多播等功能完全相同
  • 适合 CI/CD 自动化测试 —— 可以在无硬件的服务器上运行测试
  • 学习成本低 —— 一台 Linux 笔记本就能完成所有实验

限制:vcan 不支持位速率配置、不支持错误帧模拟、不模拟物理层特性。对于学习 CANOpen 协议来说,这些限制不影响使用。


2. vcan 原理

vcan 是 Linux 内核中的一个虚拟网络设备驱动,注册为 CAN 设备类型。它:

  1. 接收发送的 CAN 帧,将其放入内核网络栈
  2. 通过多播机制将帧分发给所有绑定到该 vcan 设备的 socket
  3. 行为如同一个无噪、无损、无限带宽的 CAN 总线
[进程 A] ──socket──┐
                   ├── vcan0 (内核虚拟设备) ── 帧分发给所有绑定的进程
[进程 B] ──socket──┘

3. 创建 vcan 设备

3.1 完整步骤

# 步骤 1:加载 vcan 内核模块
sudo modprobe vcan

# 步骤 2:创建虚拟 CAN 设备
sudo ip link add dev vcan0 type vcan

# 步骤 3:激活设备
sudo ip link set up vcan0

# 步骤 4:验证
ip -details link show vcan0

预期输出:

3: vcan0: <NOARP,UP,LOWER_UP> mtu 72 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/can
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0)

3.2 一键脚本

项目中提供了自动化脚本 examples/01-vcan-setup/vcan-setup.sh:

sudo ./examples/01-vcan-setup/vcan-setup.sh

该脚本会:

  1. 检查并加载 vcan 内核模块
  2. 删除已存在的同名设备(避免冲突)
  3. 创建并激活 vcan0
  4. 打印验证信息和使用提示

4. 验证 vcan 工作正常

4.1 终端 1:启动接收

candump vcan0

4.2 终端 2:发送数据

cansend vcan0 123#11223344

4.3 终端 1 应该看到

  vcan0  123   [4]  11 22 33 44

如果能看到这行输出,说明 vcan0 工作正常。


5. 多个 vcan 设备

你可以创建多个独立的 vcan 设备,模拟多条独立的 CAN 总线:

sudo ip link add dev vcan1 type vcan
sudo ip link set up vcan1

关键:vcan0 和 vcan1 是完全独立的总线,发往 vcan0 的帧不会出现在 vcan1 上。

# 终端 1:监听 vcan0
candump vcan0

# 终端 2:向 vcan1 发送
cansend vcan1 123#DEADBEEF

# 终端 1 不会收到任何帧(因为 vcan0 和 vcan1 是独立的)

如果需要跨 vcan 通信,需要使用 vcan-gw(CAN 网关)功能,这是高级主题。


6. 持久化配置

每次重启后 vcan 设备会消失。如果需要开机自动创建,有两种方法:

6.1 方法一:systemd-networkd

创建 /etc/systemd/network/vcan0.netdev:

[NetDev]
Name=vcan0
Kind=vcan

创建 /etc/systemd/network/vcan0.network:

[Match]
Name=vcan0

6.2 方法二:启动脚本

将 vcan 创建命令添加到 /etc/rc.local 或 crontab @reboot。

6.3 方法三:模块自动加载

创建 /etc/modules-load.d/vcan.conf,内容为:

vcan

然后配合 udev 规则自动创建接口。


7. 清理 vcan 设备

# 删除单个设备
sudo ip link del vcan0

# 删除所有 vcan 设备
ls /sys/class/net/vcan* 2>/dev/null | xargs -I{} basename {} | xargs -I{} sudo ip link del {}

8. 常见问题

8.1 modprobe: FATAL: Module vcan not found

原因:内核缺少 vcan 模块。

解决(Ubuntu/Debian):

sudo apt install linux-modules-extra-$(uname -r)

解决(Arch Linux):

# vcan 通常内置于主线内核
sudo modprobe vcan

原因:没有 root 权限。

解决:使用 sudo。

8.3 candump: No such device

原因:vcan0 设备不存在或未激活。

解决:

sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0

原因:缺少 iproute2 包。

解决:

sudo apt install iproute2    # Debian/Ubuntu
sudo dnf install iproute     # Fedora/CentOS

9. 关键知识点总结

知识点要点
vcan 是什么Linux 内核虚拟 CAN 网络设备
创建命令ip link add dev vcan0 type vcan
激活命令ip link set up vcan0
多设备vcan0、vcan1 等相互独立
限制不支持位速率配置、不模拟错误帧
适用场景学习、开发、测试、CI/CD

★ Insight ─────────────────────────────────────

  • vcan 是 CAN 开发者的"单元测试环境" —— 不需要硬件就能验证协议逻辑。几乎所有成熟的 CANOpen 协议栈(包括 CANopenNode)都在 CI 中使用 vcan 进行自动化测试。
  • 多 vcan 的设计模拟了实际系统中的"多条独立 CAN 总线" —— 在复杂产品中,不同子系统可能运行在独立的 CAN 总线上,通过网关互联。 ─────────────────────────────────────────────────

上一步 | 下一步

← 03-socketcan-intro.md —— SocketCAN 入门 → 05-send-receive.md —— 发送与接收实战

如果这篇文章对你有帮助,欢迎请我喝杯咖啡 ☕
Cygnus Yang 支付宝支付宝
Cygnus Yang 微信微信