1. 项目概述
最近在折腾i.MX6ULL开发板时,发现频繁烧写系统实在麻烦,于是研究了下如何在Docker容器中运行百问网的imx6ul_qemu模拟器。这套方案完美解决了我的开发痛点:既能快速验证驱动代码,又不会影响宿主机环境。整个过程涉及Docker容器配置、QEMU环境搭建、交叉编译工具链部署等多个环节,下面就把我的完整实践过程分享给大家。
这套环境特别适合以下场景:
- 需要频繁测试内核模块或驱动程序的开发者
- 想学习ARM架构但手头没有实体开发板的新手
- 需要在多台设备间快速部署统一开发环境的情况
2. 环境准备与容器配置
2.1 宿主机基础配置
在开始之前,确保宿主机已安装Docker并配置好X11转发。我使用的是Ubuntu 20.04 LTS系统,以下是关键准备步骤:
bash复制# 安装X11相关工具
sudo apt install -y xauth x11-xserver-utils
xhost +local:root
注意:xhost +local:root命令会降低X服务器的安全性,仅建议在开发环境中使用。生产环境应考虑更安全的X11转发方案。
2.2 Docker容器创建
选择Ubuntu 18.04作为基础镜像是因为百问网的QEMU系统对该版本有最佳兼容性。以下是创建容器的完整命令:
bash复制sudo docker run -it \
--name ubuntu18 \
-v ~/data_ubuntu18:/mnt/data \
--privileged \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
ubuntu:18.04 /bin/bash
参数解析:
--privileged:赋予容器完全的系统权限,QEMU需要此权限-v ~/data_ubuntu18:/mnt/data:将宿主机目录映射到容器内,方便共享文件-e DISPLAY=$DISPLAY:配置X11显示环境变量-v /tmp/.X11-unix:/tmp/.X11-unix:共享X11 Unix域套接字
3. QEMU系统部署
3.1 获取系统镜像
百问网提供了预编译好的QEMU系统镜像,通过Git克隆到本地:
bash复制mkdir -p ~/data_ubuntu18
cd ~/data_ubuntu18
git clone https://e.coding.net/weidongshan/ubuntu-18.04_imx6ul_qemu_system.git
3.2 容器内环境配置
进入容器后首先配置软件源加速下载:
bash复制sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
安装QEMU运行依赖:
bash复制apt update -y && apt install -y \
libsdl2-dev \
libsdl2-2.0-0 \
build-essential \
libpixman-1-0 \
libfdt1 \
qemu \
qemu-kvm \
libvirt-bin \
bridge-utils \
virt-manager
3.3 启动QEMU系统
进入镜像目录执行启动脚本:
bash复制cd /mnt/data/ubuntu-18.04_imx6ul_qemu_system
./qemu-imx6ull-gui.sh
成功启动后会显示图形界面,登录用户名为root,无需密码。系统关机命令为:
bash复制shutdown -h now
4. 外设驱动测试实战
4.1 LED驱动测试
QEMU系统内置了LED驱动测试程序,操作流程如下:
bash复制cd ~/led_driver_qemu/
insmod 100ask_led.ko
./ledtest /dev/100ask_led0 on # 点亮LED
./ledtest /dev/100ask_led0 off # 关闭LED
驱动加载后会创建4个LED设备节点,对应QEMU虚拟开发板上的4个LED。
4.2 按键驱动测试
按键驱动测试需要先加载两个内核模块:
bash复制cd ~/button_driver_qemu/
insmod button_drv.ko
insmod ./board_100ask_qemu_imx6ull.ko
./button_led_test
测试程序会实时显示按键状态变化,可用于验证输入子系统的工作情况。
4.3 I2C设备测试
系统内置了I2C测试工具,可以模拟I2C设备的读写操作:
bash复制cd ~/i2c_usr_test/
./i2c_usr_test /dev/i2c-0 0x50 w 1 0x55 # 写入数据
./i2c_usr_test /dev/i2c-0 0x50 r 1 # 读取数据
5. 交叉编译环境搭建
5.1 获取SDK源码
使用repo工具管理源码仓库:
bash复制git clone https://e.coding.net/codebug8/repo.git
mkdir -p 100ask_imx6ull-qemu && cd 100ask_imx6ull-qemu
../repo/repo init -u https://gitee.com/weidongshan/manifests.git -b linux-sdk -m imx6ull/100ask-imx6ull_qemu_release_v1.0.xml --no-repo-verify
../repo/repo sync -j4
5.2 安装编译工具
bash复制apt-get install -y lzop bc python3 python3-pip
ln -s /usr/bin/python3 /usr/bin/python
pip3 install requests
5.3 配置交叉编译环境
设置交叉编译工具链路径:
bash复制export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=$PATH:/mnt/data/100ask_imx6ull-qemu/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/
5.4 内核编译流程
bash复制cd /mnt/data/100ask_imx6ull-qemu/linux-4.9.88
make mrproper
make 100ask_imx6ull_qemu_defconfig
make zImage -j$(nproc)
make 100ask_imx6ull_qemu.dtb
编译完成后,内核镜像位于arch/arm/boot/zImage,设备树文件位于arch/arm/boot/dts/100ask_imx6ull_qemu.dtb。
6. 常见问题与解决方案
6.1 X11显示问题
若启动QEMU时出现显示错误,检查:
- 宿主机是否执行了
xhost +local:root - 容器启动参数是否正确设置了DISPLAY环境变量
/tmp/.X11-unix目录权限是否正确
6.2 内核模块加载失败
可能原因:
- 内核版本不匹配:确保加载的模块是为当前内核版本编译的
- 依赖缺失:使用
modinfo查看模块依赖关系 - 权限问题:容器需要
--privileged参数
6.3 QEMU运行缓慢
解决方法:
- 安装KVM加速:
apt install qemu-kvm - 启动时添加
-enable-kvm参数 - 分配更多CPU资源给容器
7. 开发技巧与优化建议
-
共享文件夹技巧:在容器外编辑代码,通过共享文件夹在容器内编译,提高开发效率
-
快速进入容器:创建alias简化容器启动命令:
bash复制alias qemu_dev='xhost +local:root && sudo docker start ubuntu18 || true && sudo docker exec -it ubuntu18 /bin/bash' -
资源监控:在容器内安装htop等工具监控系统资源使用情况
-
镜像备份:定期commit容器状态创建备份镜像:
bash复制
docker commit ubuntu18 qemu_dev_backup
这套环境我已经稳定使用了3个月,编译测试过数十个驱动模块,相比实体开发板最大的优势是可以快速回滚和快照。特别是在开发初期频繁修改代码的阶段,能节省大量等待烧录的时间。