内核实验(三):编写简单Linux内核模块,使用Qemu加载ko做测试

简介: 本文介绍了如何在QEMU中挂载虚拟分区、创建和编译简单的Linux内核模块,并在QEMU虚拟机中加载和测试这些内核模块,包括创建虚拟分区、编写内核模块代码、编译、部署以及在QEMU中的加载和测试过程。

一、篇头

为了学习Linux内核,限制于自己的编译服务器性能较弱,不便于使用Android源码进行编译;退而求其次,自己制作一个小型的linux系统,并通过Qemu来运行。使用Qemu模拟能获得更快的调试速度(只有kernel源码,编译自然比AOSP快N个倍啦!),甚至可以使用gdb进行断点调试,本文基于内核实验的前两篇文章,通过创建虚拟分区的笨方法进行测试,贵在简单。

二、QEMU:挂载虚拟分区

使用挂载虚拟分区的方式,可以和host交换文件,即作为共享分区,但缺点是不能实现文件同步。每次操作,需要host编辑好(将需要的文件放置到sd.ext4.img),再让Qemu虚拟机重新挂载sd.ext4.img。

2.1 创建 sd.ext4.img 虚拟分区

$dd if=/dev/zero of=./sd.ext4.img bs=1M count=32
$mkfs.ext4 sd.ext4.img
$mkdir sd_ext4
$sudo mount -o loop sd.ext4.img sd_ext4
$cd  sd_ext4
$sudo touch 123.txt 
$umount sd_ext4

2.2 启动 Qemu

  • 增加 -sd sd.ext4.img
szhou@bc01:~/works/qemu_linux/linux-stable$  qemu-system-arm   -nographic  -M vexpress-a9 -m 1024M -kernel arch/arm/boot/zImage   -initrd ../busybox-stable/rootfs_ext4.img.gz    -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -sd sd.ext4.img

2.3 手动挂载 sd.ext4.img

  • 透过 -sd 参数挂载,即sd-card,默认的设备节点为/dev/mmcblk0
/ # mount -t ext4 /dev/mmcblk0  /mnt
  • 查看
/mnt # ls
123.txt      lost+found
/mnt #

三、实现一个简单的KO

这一节,我们将同时实现两个简单的KO文件,并利用局部编译(模块编译)来编译他们。

3.1 目录文件
szhou@bc01:~/works/qemu_linux/linux-stable$ tree my_kmodules -L 2
my_kmodules
├── Makefile
├── test_1.c
└── test_2.c

0 directories, 3 files
szhou@bc01:~/works/qemu_linux/linux-stable$
3.2 Makefile
KDIR := /home/szhou/works/qemu_linux/linux-stable
obj-m := test_1.o test_2.o
all :
    $(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
    rm -f *.ko
3.3 编译
3.3.1 编译打印
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ make 
make -C /home/szhou/works/qemu_linux/linux-stable M=/home/szhou/works/qemu_linux/linux-stable/my_kmodules modules
make[1]: Entering directory '/home/szhou/works/qemu_linux/linux-stable'
  CC [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_1.o
  CC [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_2.o
  MODPOST /home/szhou/works/qemu_linux/linux-stable/my_kmodules/Module.symvers
  CC [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_1.mod.o
  LD [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_1.ko
  CC [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_2.mod.o
  LD [M]  /home/szhou/works/qemu_linux/linux-stable/my_kmodules/test_2.ko
make[1]: Leaving directory '/home/szhou/works/qemu_linux/linux-stable'
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$
3.3.2 生成文件
szhou@bc01:~/works/qemu_linux/linux-stable$ tree my_kmodules -L 2
my_kmodules
├── Makefile
├── modules.order
├── Module.symvers
├── test_1.c
├── test_1.ko
├── test_1.mod
├── test_1.mod.c
├── test_1.mod.o
├── test_1.o
├── test_2.c
├── test_2.ko
├── test_2.mod
├── test_2.mod.c
├── test_2.mod.o
└── test_2.o

0 directories, 15 files
szhou@bc01:~/works/qemu_linux/linux-stable$
3.4 检查:objdump

通过反编译ko文件,确认Makefile实现无问题,test_1.ko和test_2.ko使用各自源文件做了编译。

3.4.1 objdump -dS test_1.ko
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ arm-linux-gnueabi-objdump -dS test_1.ko 

test_1.ko:     file format elf32-littlearm


Disassembly of section .init.text:

00000000 <init_module>:
#include <linux/module.h>

static int __init test_1_init(void)
{
   
   
   0:   e92d4010        push    {
   
   r4, lr}
    printk(KERN_EMERG "test_1_init\n");
   4:   e3000000        movw    r0, #0
   8:   e3400000        movt    r0, #0
   c:   ebfffffe        bl      0 <_printk>
    return 0;
}
  10:   e3a00000        mov     r0, #0
  14:   e8bd8010        pop     {
   
   r4, pc}

Disassembly of section .exit.text:

00000000 <cleanup_module>:

static void __exit test_1_exit(void)
{
   
   
    printk("test_1_exit\n");
   0:   e3000000        movw    r0, #0
   4:   e3400000        movt    r0, #0
   8:   eafffffe        b       0 <_printk>

Disassembly of section .plt:

0000000c <.plt>:
        ...
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$
3.4.2 objdump -dS test_2.ko
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ arm-linux-gnueabi-objdump -dS test_2.ko  

test_2.ko:     file format elf32-littlearm


Disassembly of section .init.text:

00000000 <init_module>:
#include <linux/module.h>

static int __init test_2_init(void)
{
   
   
   0:   e92d4010        push    {
   
   r4, lr}
    printk(KERN_EMERG "test_2_init\n");
   4:   e3000000        movw    r0, #0
   8:   e3400000        movt    r0, #0
   c:   ebfffffe        bl      0 <_printk>
    return 0;
}
  10:   e3a00000        mov     r0, #0
  14:   e8bd8010        pop     {
   
   r4, pc}

Disassembly of section .exit.text:

00000000 <cleanup_module>:

static void __exit test_2_exit(void)
{
   
   
    printk("test_2_exit\n");
   0:   e3000000        movw    r0, #0
   4:   e3400000        movt    r0, #0
   8:   eafffffe        b       0 <_printk>

Disassembly of section .plt:

0000000c <.plt>:
        ...
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$

四、部署

如下在host机器上,挂载SD虚拟分区,并将KO文件复制到分区内。

#(1)返回linux kernel source code 根目录
szhou@bc01:~/works/qemu_linux/linux-stable/my_kmodules$ cd ..

#(2)使用sudo权限,挂载 sd.ext4.img 虚拟分区到sd_ext4目录
szhou@bc01:~/works/qemu_linux/linux-stable$ sudo mount -o loop sd.ext4.img sd_ext4
[sudo] password for szhou: 

#(3)复制编译好的ko文件到虚拟分区中
szhou@bc01:~/works/qemu_linux/linux-stable$ sudo cp -rf my_kmodules/test_1.ko sd_ext4/
szhou@bc01:~/works/qemu_linux/linux-stable$ sudo cp -rf my_kmodules/test_2.ko sd_ext4/ 

#(4) 卸载
szhou@bc01:~/works/qemu_linux/linux-stable$ sudo umount sd_ext4 
szhou@bc01:~/works/qemu_linux/linux-stable$
  • 操作如下图所示
    在这里插入图片描述

五、加载并测试

5.1 启动 Qemu 并挂载
  • 增加 -sd sd.ext4.img
szhou@bc01:~/works/qemu_linux/linux-stable$  qemu-system-arm   -nographic  -M vexpress-a9 -m 1024M -kernel arch/arm/boot/zImage   -initrd ../busybox-stable/rootfs_ext4.img.gz    -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -sd sd.ext4.img 

/ # mount -t ext4 /dev/mmcblk0  /mnt
5.2 手动挂载 sd.ext4.img
/ # mount -t ext4 /dev/mmcblk0  /mnt
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null). Quota mode: disabled.
/ # ls
bin         etc         lost+found  proc        sys         usr
dev         linuxrc     mnt         sbin        tmp
/ # cd /mnt/
/mnt # ls
111.txt     lost+found  test_1.ko   test_2.ko
/mnt #
5.3 加载 ko modules
#(1)查看SD虚拟分区
/ # cd /mnt/
/mnt # ls
111.txt     lost+found  test_1.ko   test_2.ko

#(2)测试 test_1.ko 
/mnt # insmod test_1.ko 
test_1: loading out-of-tree module taints kernel.
test_1_init
/mnt # lsmod
test_1 16384 0 - Live 0x7f000000 (O)
/mnt # rmmod test_1.ko 
test_1_exit

#(3)测试 test_2.ko 
/mnt # insmod test_2.ko 
test_2_init
/mnt # rmmod  test_2.ko 
test_2_exit
/mnt #
  • 运行效果下图所示
    在这里插入图片描述
相关文章
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的1024QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的1024QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集和vio在线SNR设置模块,支持不同SNR条件下的性能测试。1024QAM调制将10比特映射到复平面上的1024个星座点之一,实现高效数据传输。硬件测试结果表明,在SNR=32dB和40dB时,系统表现出良好的性能。Verilog核心程序展示了各模块的连接与功能实现。
413 7
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的MSK调制解调系统系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于FPGA实现MSK调制解调系统,采用Verilog开发,包含同步模块、高斯信道模拟、误码率统计等功能。相比仿真版本,新增ILA数据采集与VIO在线SNR设置模块。通过硬件测试验证,展示不同SNR(如10dB和16dB)下的性能表现。研究聚焦软件无线电领域,优化算法复杂度以适应硬件限制,利用MSK恒定包络、相位连续等特性提升频谱效率。核心代码实现信号生成、调制解调、滤波及误码统计,提供完整的硬件设计与分析方案。
586 19
|
数据采集 移动开发 算法
【硬件测试】基于FPGA的QPSK调制+软解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于FPGA实现QPSK调制与软解调系统,包含Testbench、高斯信道、误码率统计模块,并支持不同SNR设置。硬件版本新增ILA在线数据采集和VIO在线SNR设置功能,提供无水印完整代码及测试结果。通过VIO分别设置SNR为6dB和12dB,验证系统性能。配套操作视频便于用户快速上手。 理论部分详细解析QPSK调制原理及其软解调实现过程,涵盖信号采样、相位估计、判决与解调等关键步骤。软解调通过概率估计(如最大似然法)提高抗噪能力,核心公式为*d = d_hat / P(d_hat|r[n])*,需考虑噪声对信号点分布的影响。 附Verilog核心程序代码及注释,助力理解与开发。
473 5
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4ASK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的4ASK调制解调系统的硬件测试版本,该系统包括testbench、高斯信道模块和误码率统计模块,并新增了ILA在线数据采集和VIO在线SNR设置功能。通过VIO设置不同SNR(如15dB和25dB),实现了对系统性能的实时监测与调整。4ASK是一种通过改变载波幅度表示数据的数字调制方式,适用于多种通信场景。FPGA平台的高效性和灵活性使其成为构建高性能通信系统的理想选择。
424 17
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的16QAM调制+软解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于之前开发的16QAM调制与软解调系统,增加了硬件测试功能。该系统包含FPGA实现的16QAM调制、软解调、高斯信道、误码率统计模块,并新增了ILA在线数据采集和VIO在线SNR设置模块。通过硬件测试,验证了不同SNR条件下的系统性能。16QAM软解调通过比较接收信号采样值与16个调制点的距离,选择最近的调制点来恢复原始数据。核心Verilog代码实现了整个系统的功能,包括SNR设置、信号处理及误码率统计。硬件测试结果表明系统在不同SNR下表现良好,详细操作步骤可参考配套视频。
408 13
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4FSK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文基于之前的文章《基于FPGA的4FSK调制解调系统》,增加了ILA在线数据采集模块和VIO在线SNR设置模块,实现了硬件测试版本。通过VIO设置不同SNR(如10dB和20dB),并展示了ILA采集的数据结果。四频移键控(4FSK)是一种数字调制方法,利用四个不同频率传输二进制数据,具有较高的频带利用率和抗干扰性能。输入的二进制数据分为两组,每组两个比特,对应四个频率f1、f2、f3、f4,分别代表二进制组合00、01、10、11。调制过程中选择相应频率输出,并进行幅度调制以增强抗干扰能力。接收端通过带通滤波器提取信号并还原为原始二进制数据。
414 7
|
数据采集 算法 数据处理
【硬件测试】基于FPGA的256QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的256QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集和vio在线SNR设置模块,支持不同信噪比(如30dB和40dB)的仿真测试,并提供配套操作视频。256QAM调制方案每个符号携带8比特信息,通过复数值星座图映射实现高效传输。Verilog代码展示了核心模块设计,包括SNR设置、数据处理和ILA测试分析,确保系统在实际硬件环境中的稳定性和性能。
393 2
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的16QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的16QAM基带通信系统硬件测试版本。该系统在仿真基础上增加了ILA在线数据采集和VIO在线SNR设置模块,支持不同信噪比(如15dB、25dB)的测试。16QAM是一种正交幅度调制方式,通过两路4ASK信号叠加实现,每个符号包含4比特信息。系统采用正交调幅法生成16QAM信号,并通过DAC转换为模拟信号。解调时使用正交相干解调,经低通滤波器恢复电平信号。开发板内完成发射与接收,无需定时同步模块。代码可移植至其他开发板,具体步骤见配套文档。
362 2
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的2ASK调制解调系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍基于FPGA的2ASK调制解调系统,涵盖仿真效果、理论知识、Verilog核心程序及开发板使用说明。系统包含testbench、高斯信道模块和误码率统计模块,支持不同SNR设置。硬件测试版本增加了ILA在线数据采集和VIO在线SNR设置功能。2ASK调制通过改变载波振幅传输二进制信号,FPGA实现包括系统设计、Verilog编码、仿真测试和硬件部署。详细操作步骤见配套视频,代码适用于多种开发板,提供移植方法。
384 1
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的64QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的64QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集模块和vio在线SNR设置模块,支持不同SNR条件下的仿真与测试。通过设置SNR为25dB和30dB进行测试,验证了系统的可行性和性能。此外,本文详细阐述了64QAM调制解调的工作原理,包括信号生成、调制、解调及误码率测试等环节,并提供了Verilog核心程序代码。
326 0