内核实验(三):编写简单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 #
  • 运行效果下图所示
    在这里插入图片描述
相关文章
|
10月前
|
安全 网络协议 Linux
深入理解Linux内核模块:加载机制、参数传递与实战开发
本文深入解析了Linux内核模块的加载机制、参数传递方式及实战开发技巧。内容涵盖模块基础概念、加载与卸载流程、生命周期管理、参数配置方法,并通过“Hello World”模块和字符设备驱动实例,带领读者逐步掌握模块开发技能。同时,介绍了调试手段、常见问题排查、开发规范及高级特性,如内核线程、模块间通信与性能优化策略。适合希望深入理解Linux内核机制、提升系统编程能力的技术人员阅读与实践。
890 1
|
10月前
|
监控 Ubuntu Linux
什么Linux,Linux内核及Linux操作系统
上面只是简单的介绍了一下Linux操作系统的几个核心组件,其实Linux的整体架构要复杂的多。单纯从Linux内核的角度,它要管理CPU、内存、网卡、硬盘和输入输出等设备,因此内核本身分为进程调度,内存管理,虚拟文件系统,网络接口等4个核心子系统。
1020 0
|
10月前
|
Web App开发 缓存 Rust
|
10月前
|
Ubuntu 安全 Linux
Ubuntu 发行版更新 Linux 内核,修复 17 个安全漏洞
本地攻击者可以利用上述漏洞,攻击 Ubuntu 22.10、Ubuntu 22.04、Ubuntu 20.04 LTS 发行版,导致拒绝服务(系统崩溃)或执行任意代码。
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
12月前
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
1570 23
|
SQL 安全 测试技术
2025接口测试全攻略:高并发、安全防护与六大工具实战指南
本文探讨高并发稳定性验证、安全防护实战及六大工具(Postman、RunnerGo、Apipost、JMeter、SoapUI、Fiddler)选型指南,助力构建未来接口测试体系。接口测试旨在验证数据传输、参数合法性、错误处理能力及性能安全性,其重要性体现在早期发现问题、保障系统稳定和支撑持续集成。常用方法包括功能、性能、安全性及兼容性测试,典型场景涵盖前后端分离开发、第三方服务集成与数据一致性检查。选择合适的工具需综合考虑需求与团队协作等因素。
2094 24
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
1205 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
991 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡