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 命令并返回模拟响应。
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
| 参数 | 示例值 | 说明 |
|---|---|---|
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 常见错误与解决
| 错误现象 | 根因 | 解决方案 |
|---|---|---|
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 清理内部状态,防止虚拟控制器因未处理的异常事件而挂起。