基于QEMU的Linux Driver开发环境的配置

1 工具集合

  • QEMU 5.2.0
  • Linux Kernel 4.18
  • Busybox 1.32.1

2 配置Linux Kernel

笔者用Linux 4.18, 配置文件选用vexpress_defconfig, 如果关心Linux Kernel编译流程,请移步Linux Kernel 编译流程(1)

#Linux kernel
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.18.tar.xz
tar xvf linux-4.18.tar.xz
cd linux-4.18
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- vexpress_defconfig
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- dtbs

编译完成后会在arch/arm/boot/目录下生成zImage

3 配置QEMU

编译QEMU过程中,可能会出现错误,请移步Install QEMU 5.1.50

wget https://download.qemu.org/qemu-5.2.0.tar.xz
tar xvJf qemu-5.2.0.tar.xz
cd qemu-5.2.0
mkdir build && cd build
../configure
make

4 启动Linux Kernel

QEMU启动LinuxKernel,笔者将命令放在run_linuxkernel.sh文件中,笔者目录如图所示

sudo qemu/build/qemu-system-arm -M vexpress-a9 -nographic -smp 4 -m 512 -kernel linux-4.18/arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb linux-4.18/arch/arm/boot/dts/vexpress-v2p-ca9.dtb

启动后会出现错误

错误发生的原因是没有文件系统,这里配置文件系统为Initial Ram filesystem

5 配置Busybox

笔者采用Busybox 1.32.1来配置文件系统

tar xvf busybox-1.32.1.tar.bz2
cd busybox-1.32.1
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig

选择BusyboxSettings->Build Options,将busybox设置为静态编译过程

采用下面的命令编译和安装busybox, 执行完命令后,会在busybox目录中生成_install目录, 里面包含 bin linuxrc sbin usr

sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install

6 再次配置Linux Kernel

首先我们将busybox生成的_install目录拷贝到Linuxkernel目录下,然后打开配置文件,将红框中的内容填成_install

我们再次进入linux-4.18的 _install 目录中, 做如下操作。

  • 添加如下目录 dev/ etc/

  • 进入dev目录下添加 console null 文件

sudo mknod console c 5 1
sudo mknod null c 1 3

进入etc/目录中,添加fstab,inittab文件和init.d目录

其中fstab的内容如下:

proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
debugfs /sys/kernel/debug debugfs defaults 0 0

inittab的内容如下:

::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r



![](images/20210125205346676.PNG)

rcS的内容如下:

```shell
 #! /bin/sh
 mkdir -p /proc /tmp /sys /mnt
 /bin/mount -a
 mkdir -p /dev/pts
 mount -t devpts devpts /dev/pts
 echo /sbin/mdev > /proc/sys/kernel/hotplug
 mdev -s

添加完文件后还得修改rcS文件权限,不然会有权限问题,在启动过程中会发现

7 启动Linux Kernel

再次用QEMU启动Linux Kernel,大功告成.

8 举个小栗子-编写驱动

笔者以hello world开始 hello.c

#include <linux/init.h>
#include <linux/module.h>

static int __init hello_init(void)
{
    printk(KERN_INFO "hello world, this is eric\n");
    return 0;
}

module_init(hello_init);

static void __exit hello_exit(void)
{
    printk(KERN_INFO "hello world exit\n");
}

module_exit(hello_exit);

MODULE_AUTHOR("eric dong");
MODULE_LICENSE("GPL v2");

Makefile

KVERS = $(shell uname -r)
KBUILD_CFLAGS += -fno-pic
#kernel modules
obj-m := hello.o
mod-dir := ~/driver_study/linux-4.18/lib/modules/4.18.0/build
build: kernel_modules

kernel_modules:
        make -C $(mod-dir) M=$(CURDIR) ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules
clean:
        make -C $(mod-dir) M=$(CURDIR) ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- clean

在编译之前,笔者发现~/driver_stud/linux-4.18/lib目录下没有modules, 在顶层Makefile发现需要执行modules_install,于是查看,得知需要在当前目录下创建

KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
#MODLIB    = $(INSTALL_MOD_PATH)/lib/modules/4.18.0
MODLIB    = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
#Target to install modules
PHONY += modules_install
modules_install: _modinst_
_modinst_:
    $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst

所以执行命令 sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- INSTALL_MOD_PATH=. 当前目录.=linux-4.18/,执行完命令后,就能在/lib/下发现modules目录.

接着执行命令行make编译得到hello.ko 最后在QEMU中执行hello.ko, 如图所示

Done. Hope helpful for you guys.