4. 搭建Linux下的Mock环境

4.1 原理概述

Mock 蓝牙测试环境的核心是在 Linux 用户空间模拟蓝牙控制器与主机的通信接口,使上层协议栈和应用程序无需真实硬件即可完成功能验证。BlueZ 作为 Linux 官方蓝牙协议栈,提供了完整的虚拟化支持:hci_vhci 内核驱动用于创建虚拟 HCI 控制器,btvirt 工具在用户空间模拟控制器行为,两者结合可构建完全脱离硬件的 Mock 环境。

整个 Mock 环境的分层结构如下:

  • 应用层:蓝牙应用或测试脚本通过 D-Bus 或 Socket 与 BlueZ 通信。
  • 协议栈层:BlueZ 的 bluetoothd 守护进程管理 HCI 通道和连接状态。
  • HCI 层:虚拟 HCI 接口(vHCI)将标准 HCI 命令转发到用户空间模拟器。
  • 模拟器层:btvirt 或自定义后端解析 HCI 命令并返回模拟响应。
Mock 蓝牙环境搭建流程 Mock 蓝牙环境搭建流程 ① 安装 BlueZ 套件 apt / 源码编译 ② 加载内核模块 btusb / hci_vhci ③ 配置 HCI 接口 hciconfig hci0 up ④ 创建虚拟设备 btvirt / vhci ⑤ 验证 Mock 环境 hciconfig / hcitool 关键命令备忘 1. sudo apt install bluez 2. sudo modprobe hci_vhci 3. sudo hciconfig hci0 up 4. btvirt -d 5. hciconfig -a

4.2 环境准备

Mock 环境依赖 Linux 内核 5.10+ 和 BlueZ 5.55+。建议使用 Ubuntu 22.04 / Debian 12 或同等发行版。开始前确认以下基础条件:

  • 内核支持 CONFIG_BT_HCI_VHCI(虚拟 HCI 驱动)
  • 已安装编译工具链(gcc、make、cmake)
  • 具备 root 权限或 sudo 免密执行能力
  • 系统未占用 hci0 接口(可用 hciconfig 检查)
环境检查命令:
uname -r
hciconfig -a
lsmod | grep bt
dpkg -l bluez 2>/dev/null || echo "BlueZ 未安装"

4.3 安装 BlueZ 套件

推荐通过包管理器快速安装,也可从源码编译以获取最新特性或定制补丁。

4.3.1 包管理器安装(快速)

sudo apt update
sudo apt install -y bluez bluez-tools bluez-utils bluetooth
sudo systemctl enable bluetooth
sudo systemctl start bluetooth

4.3.2 源码编译安装(定制)

git clone https://github.com/bluez/bluez.git
cd bluez
./bootstrap
./configure --prefix=/usr --sysconfdir=/etc --enable-test
make -j$(nproc)
sudo make install
sudo ldconfig

安装完成后验证版本:

bluetoothctl --version
bluetoothd --version
提示: 如果使用源码安装,务必启用 --enable-test 选项,否则 btvirt 等测试工具不会被编译。

4.4 加载内核模块与配置 HCI

Mock 环境需要加载 hci_vhci 内核模块来创建虚拟 HCI 控制器,同时可按需加载 btusb 模块(若宿主机有蓝牙硬件但本次测试不使用)。

4.4.1 加载模块

sudo modprobe hci_vhci
sudo modprobe btusb
lsmod | grep -E "hci_vhci|btusb"

4.4.2 配置 HCI 接口

加载模块后,系统会自动创建虚拟 HCI 接口(通常为 hci0)。使用 hciconfig 进行基本配置:

# 查看所有 HCI 接口
sudo hciconfig -a

# 启动 hci0 接口
sudo hciconfig hci0 up

# 设置设备名称和类别
sudo hciconfig hci0 name "Mock-BT-Device"
sudo hciconfig hci0 class 0x1f0100

# 验证配置
sudo hciconfig hci0
HCI 接口关键配置参数
参数 示例值 说明
name Mock-BT-Device 蓝牙设备广播名称,最大 248 字节
class 0x1f0100 设备类别(如计算机/手机/外设)
piscan 启用/禁用 页扫描 + 查询扫描,使设备可被发现
lm MASTER, SLAVE 链路角色偏好

4.5 创建虚拟蓝牙设备

虚拟设备通过 btvirt 工具实现,它在用户空间模拟一个完整的蓝牙控制器,并与内核 vHCI 驱动对接。创建后,上层应用将看到一个真实的 HCI 接口。

4.5.1 使用 btvirt 创建默认虚拟设备

# 启动一个虚拟蓝牙控制器
sudo btvirt -d

# 以调试模式运行(打印所有 HCI 事件)
sudo btvirt -d -l debug

执行后,系统会新增一个 HCI 接口(如 hci1),可用 hciconfig 查看。

4.5.2 通过 vHCI 手动创建多个虚拟控制器

# 创建第 1 个虚拟控制器
sudo hciconfig hci1 up
sudo hciconfig hci1 name "Mock-Sensor-1"

# 创建第 2 个虚拟控制器
sudo hciconfig hci2 up
sudo hciconfig hci2 name "Mock-Sensor-2"
注意: 虚拟控制器数量受内核参数 max_vhci 限制(默认 2)。如需更多,可在加载模块时指定:sudo modprobe hci_vhci max_vhci=8。

4.5.3 使用 Python + PyBlueZ 以编程方式创建

# 安装 PyBlueZ
sudo apt install -y python3-pip
pip3 install pybluez

# 创建虚拟设备示例脚本
cat < /tmp/create_mock.py
import bluetooth

# 打开一个虚拟 HCI socket
sock = bluetooth.BluetoothSocket(bluetooth.HCI)
sock.bind(("", bluetooth.HCI_DEV_NONE))
sock.listen(1)
print("Mock 设备监听中... 按 Ctrl+C 退出")
try:
    conn, addr = sock.accept()
    print(f"收到连接: {addr}")
except KeyboardInterrupt:
    pass
finally:
    sock.close()
EOF
sudo python3 /tmp/create_mock.py

4.6 调试与验证

Mock 环境搭建完成后,通过以下工具链进行端到端验证,确保虚拟设备可被扫描、连接和通信。

  • hciconfig:检查接口状态、名称、类别和标志位。
  • hcitool:执行扫描、查询、连接等 HCI 层操作。
  • btmon:监控 HCI 数据包,用于协议级调试。
  • bluetoothctl:D-Bus 交互工具,验证高层服务发现和配对。
# 1. 检查虚拟接口状态
sudo hciconfig -a | grep -E "hci|Name|Class"

# 2. 执行设备扫描(应能发现其他虚拟或真实设备)
sudo hcitool scan

# 3. 启动 btmon 监控 HCI 流量
sudo btmon &

# 4. 使用 bluetoothctl 交互验证
echo -e "power on\nscan on\nquit" | sudo bluetoothctl

# 5. 查看蓝牙守护进程日志
journalctl -u bluetooth -n 20 --no-pager
验证通过标准:
  • hciconfig hci0 显示 UP RUNNING 状态。
  • hcitool scan 在 5 秒内返回设备列表(至少含自身 Mock 设备)。
  • btmon 中能看到 HCI_Command_Complete 事件。
  • bluetoothctl show 输出中 Controller 行显示虚拟接口地址。

4.7 常见错误与解决

Mock 环境搭建常见问题排查
错误现象 根因 解决方案
Can't open HCI socket: Permission denied 非 root 用户执行 HCI 操作 使用 sudo 或添加用户到 bluetooth 组
hci_vhci: Unknown symbol 内核不支持或模块版本不匹配 升级内核至 5.10+,重新编译模块
btvirt: error while loading shared libraries BlueZ 库路径未更新 执行 sudo ldconfig 或设置 LD_LIBRARY_PATH
hci0: Device or resource busy 接口被其他进程占用 sudo hciconfig hci0 reset 或重启 bluetooth 服务
扫描不到任何设备 虚拟设备未启用页扫描 sudo hciconfig hci0 piscan

4.8 性能与稳定性优化

Mock 环境在持续集成或大规模并发测试场景下,需要关注以下优化点:

  • 增大 vHCI 队列深度:加载模块时指定 max_vhci=16 和 buf_size=4096,避免高并发丢包。
  • 关闭非必要服务:停止 bluetooth 服务外的 NetworkManager 蓝牙插件、pulseaudio 蓝牙模块,减少干扰。
  • CPU 亲和性绑定:将 btvirt 和测试进程绑定到同一 CPU 核心,降低上下文切换延迟。
  • 使用 polling 模式:在 btvirt 启动参数中添加 --poll,减少事件驱动开销。
  • 日志轮转:btmon 长时间运行时启用 --rotate 100M 限制日志文件大小。
# 优化示例:加载模块时调整参数
sudo modprobe hci_vhci max_vhci=16 buf_size=4096

# 启动 btvirt 并绑定 CPU
taskset -c 2 sudo btvirt -d --poll

# 验证优化效果
sudo hciconfig -a | grep "RX bytes"
稳定性建议: Mock 环境长时间运行(超过 4 小时)时,建议每 30 分钟执行一次 sudo hciconfig hci0 reset 清理内部状态,防止虚拟控制器因未处理的异常事件而挂起。