前言

  • 默认Linux 内核驱动,可以模块编译为 *.ko 文件,不编译进内核

  • 默认开发Linux 内核驱动,驱动一般放在Linux 内核源码中,如 drivers 目录

  • 本篇尝试在 Linux kernel 源码外部编译 Linux 内核驱动模块

开发环境

  • Win10 64 位 + VMware Workstation Pro 16

  • 虚拟机 安装 ubuntu 20.04

  • 内核驱动运行于:ARM 平台 qemu vexpress-a9

hello 内核驱动

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>static int __init hello_init(void)
{printk(KERN_INFO  "%s : enter\n", __func__);return 0;
}static void __exit hello_exit(void)
{printk(KERN_INFO "%s : enter\n", __func__);
}module_init(hello_init);
module_exit(hello_exit);MODULE_AUTHOR("zhangsz");
MODULE_DESCRIPTION("hello");
MODULE_LICENSE("GPL");

Makefile 文件

  • 因为要运行在 ARM vexpress-a9 平台 的qemu 中,所以Linux 驱动编译需要使用交叉编译
obj-m :=hello.oKERN_DIR := /home/rtt/linux/kernel/linux-6.1.3
CUR_DIR := $(shell pwd)all:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERN_DIR) M=$(CUR_DIR) modules
clean:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERN_DIR) M=$(CUR_DIR) clean
  • 注意虽然在 Linux kernel 源码外部编译,依旧需要存在Linux kernel 的源码,make -C 可以制定 Linux kernel 源码目录

  • 我当前的Linux kernel 目录为:KERN_DIR := /home/rtt/linux/kernel/linux-6.1.3

make 编译

rtt@ubuntu:/mnt/hgfs/tools/linux/codes/hello$ ls
hello.c  Makefilertt@ubuntu:/mnt/hgfs/tools/linux/codes/hello$ make
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C /home/rtt/linux/kernel/linux-6.1.3 M=/mnt/hgfs/tools/linux/codes/hello modules
make[1]: Entering directory '/home/rtt/linux/kernel/linux-6.1.3'CC [M]  /mnt/hgfs/tools/linux/codes/hello/hello.o
make[2]: Warning: File '/mnt/hgfs/tools/linux/codes/hello/modules.order' has modification time 0.58 s in the futureMODPOST /mnt/hgfs/tools/linux/codes/hello/Module.symvers
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
make[2]: Warning: File '/mnt/hgfs/tools/linux/codes/hello/hello.o' has modification time 0.56 s in the futureCC [M]  /mnt/hgfs/tools/linux/codes/hello/hello.mod.oLD [M]  /mnt/hgfs/tools/linux/codes/hello/hello.ko
make[2]: warning:  Clock skew detected.  Your build may be incomplete.
make[1]: Leaving directory '/home/rtt/linux/kernel/linux-6.1.3'rtt@ubuntu:/mnt/hgfs/tools/linux/codes/hello$ ls
hello.c  hello.ko  hello.mod  hello.mod.c  hello.mod.o  hello.o  Makefile  modules.order  Module.symvers

运行

  • 编译的产物: hello.ko,由于使用的交叉编译工具编译的,所以在 ubuntu 上直接 sudo insmod hello.ko 是无法工作的

  • 需要把 hello.ko 拷贝到 qemu 的 根文件系统中,然后运行 qemu

  • 启动 qemu,主要这里的 /dev/sdb2 为 存放 qemu 根文件系统的分区

sudo qemu-system-arm -M vexpress-a9 -m 512M -dtb vexpress-v2p-ca9.dtb -kernel zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd  /dev/sdb2
rtt@ubuntu:~/linux/qemu$ ls
boot_qemu.sh  create_rootfs.sh  make_boot.sh  rootfs_0112  vexpress-v2p-ca9.dtb  zImagertt@ubuntu:~/linux/qemu$ sudo qemu-system-arm -M vexpress-a9 -m 512M -dtb vexpress-v2p-ca9.dtb -kernel zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd  /dev/sdb2
[sudo] password for rtt:
WARNING: Image format was not specified for '/dev/sdb2' and probing guessed raw.Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.Specify the 'raw' format explicitly to remove the restrictions.
Booting Linux on physical CPU 0x0
Linux version 6.1.3 (rtt@ubuntu) (arm-linux-gnueabihf-gcc (GCC) 13.0.0 20221001 (experimental) [master revision 5299155bb80e90df822e1eebc9f9a0c8e4505a46], GNU ld (Linaro_Binutils-2022.10) 2.39.50.20221001) #1 SMP Wed Jan 11 17:26:26 PST 2023
CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
OF: fdt: Machine model: V2P-CA9
Memory policy: Data cache writeback
Reserved memory: created DMA memory pool at 0x4c000000, size 8 MiB
OF: reserved mem: initialized node vram@4c000000, compatible id shared-dma-pool
cma: Reserved 16 MiB at 0x7f000000
Zone ranges:Normal   [mem 0x0000000060000000-0x000000007fffffff]
Movable zone start for each node
Early memory node rangesnode   0: [mem 0x0000000060000000-0x000000007fffffff]
Initmem setup node 0 [mem 0x0000000060000000-0x000000007fffffff]
CPU: All CPU(s) started in SVC mode.
percpu: Embedded 15 pages/cpu s30612 r8192 d22636 u61440
Built 1 zonelists, mobility grouping on.  Total pages: 130048
Kernel command line: root=/dev/mmcblk0 rw console=ttyAMA0
printk: log_buf_len individual max cpu contribution: 4096 bytes
printk: log_buf_len total cpu_extra contributions: 12288 bytes
printk: log_buf_len min size: 16384 bytes
printk: log_buf_len: 32768 bytes
printk: early log buf free: 14896(90%)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes, linear)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes, linear)
mem auto-init: stack:all(zero), heap alloc:off, heap free:off
Memory: 489776K/524288K available (8192K kernel code, 643K rwdata, 1860K rodata, 1024K init, 180K bss, 18128K reserved, 16384K cma-reserved)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
trace event string verifier disabled
rcu: Hierarchical RCU implementation.
rcu:    RCU event tracing is enabled.
rcu:    RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
GIC CPU mask not found - kernel will fail to boot.
GIC CPU mask not found - kernel will fail to boot.
L2C: platform modifies aux control register: 0x02020000 -> 0x02420000
L2C: DT/platform modifies aux control register: 0x02020000 -> 0x02420000
L2C-310 enabling early BRESP for Cortex-A9
L2C-310 full line of zeros enabled for Cortex-A9
L2C-310 dynamic clock gating disabled, standby mode disabled
L2C-310 cache controller enabled, 8 ways, 128 kB
L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x46420001
rcu: srcu_init: Setting srcu_struct sizes based on contention.
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
clocksource: arm,sp804: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275 ns
smp_twd: clock not found -2
Console: colour dummy device 80x30
Calibrating local timer... 96.14MHz.
Calibrating delay loop... 875.72 BogoMIPS (lpj=4378624)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
CPU: Testing write buffer coherency: ok
CPU0: Spectre v2: using BPIALL workaround
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x60100000 - 0x60100060
rcu: Hierarchical SRCU implementation.
rcu:    Max phase no-delay instances is 1000.
smp: Bringing up secondary CPUs ...
smp: Brought up 1 node, 1 CPU
SMP: Total of 1 processors activated (875.72 BogoMIPS).
CPU: All CPU(s) started in SVC mode.
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 0
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 1024 (order: 4, 65536 bytes, linear)
NET: Registered PF_NETLINK/PF_ROUTE protocol family
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor ladder
hw-breakpoint: debug architecture 0x4 unsupported.
Serial: AMBA PL011 UART driver
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
i2c 0-0039: Fixing up cyclic dependency with 1001f000.clcd
i2c 0-0039: Fixing up cyclic dependency with 10020000.clcd
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
PTP clock support registered
Advanced Linux Sound Architecture Driver Initialized.
clocksource: Switched to clocksource arm,sp804
NET: Registered PF_INET protocol family
IP idents hash table entries: 8192 (order: 4, 65536 bytes, linear)
tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
TCP established hash table entries: 4096 (order: 2, 16384 bytes, linear)
TCP bind hash table entries: 4096 (order: 4, 65536 bytes, linear)
TCP: Hash tables configured (established 4096 bind 4096)
UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
NET: Registered PF_UNIX/PF_LOCAL protocol family
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
hw perfevents: enabled with armv7_cortex_a9 PMU driver, 5 counters available
workingset: timestamp_bits=30 max_order=17 bucket_order=0
squashfs: version 4.0 (2009/01/31) Phillip Lougher
jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
9p: Installing v9fs 9p2000 file system support
io scheduler mq-deadline registered
io scheduler kyber registered
OF: graph: no port node found in /bus@40000000/motherboard-bus@40000000/iofpga@7,00000000/i2c@16000/dvi-transmitter@60
sii902x 0-0060: supply iovcc not found, using dummy regulator
sii902x 0-0060: supply cvcc12 not found, using dummy regulator
physmap-flash 40000000.flash: physmap platform flash device: [mem 0x40000000-0x43ffffff]
40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
physmap-flash 40000000.flash: physmap platform flash device: [mem 0x44000000-0x47ffffff]
40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
Concatenating MTD devices:
(0): "40000000.flash"
(1): "40000000.flash"
into device "40000000.flash"
physmap-flash 48000000.psram: physmap platform flash device: [mem 0x48000000-0x49ffffff]
smsc911x 4e000000.ethernet eth0: MAC Address: 52:54:00:12:34:56
isp1760 4f000000.usb: isp1760 bus width: 32, oc: digital
isp1760 4f000000.usb: NXP ISP1760 USB Host Controller
isp1760 4f000000.usb: new USB bus registered, assigned bus number 1
isp1760 4f000000.usb: Scratch test failed. 0x00000000
isp1760 4f000000.usb: can't setup: -19
isp1760 4f000000.usb: USB bus 1 deregistered
usbcore: registered new interface driver usb-storage
rtc-pl031 10017000.rtc: registered as rtc0
rtc-pl031 10017000.rtc: setting system clock to 2023-02-09T06:31:31 UTC (1675924291)
mmci-pl18x 10005000.mmci: Got CD GPIO
mmci-pl18x 10005000.mmci: Got WP GPIO
mmci-pl18x 10005000.mmci: mmc0: PL181 manf 41 rev0 at 0x10005000 irq 35,36 (pio)
ledtrig-cpu: registered to indicate activity on CPUs
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
aaci-pl041 10004000.aaci: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 37
aaci-pl041 10004000.aaci: FIFO 512 entries
NET: Registered PF_PACKET protocol family
9pnet: Installing 9P2000 support
Registering SWP/SWPB emulation handler
10009000.uart: ttyAMA0 at MMIO 0x10009000 (irq = 38, base_baud = 0) is a PL011 rev1
input: AT Raw Set 2 keyboard as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10006000.kmi/serio0/input/input0
mmc0: new SDHC card at address 4567
mmcblk0: mmc0:4567 QEMU! 20.0 GiB
printk: console [ttyAMA0] enabled
1000a000.uart: ttyAMA1 at MMIO 0x1000a000 (irq = 39, base_baud = 0) is a PL011 rev1
1000b000.uart: ttyAMA2 at MMIO 0x1000b000 (irq = 40, base_baud = 0) is a PL011 rev1
1000c000.uart: ttyAMA3 at MMIO 0x1000c000 (irq = 41, base_baud = 0) is a PL011 rev1
drm-clcd-pl111 1001f000.clcd: assigned reserved memory node vram@4c000000
drm-clcd-pl111 1001f000.clcd: using device-specific reserved memory
drm-clcd-pl111 1001f000.clcd: core tile graphics present
drm-clcd-pl111 1001f000.clcd: this device will be deactivated
drm-clcd-pl111 1001f000.clcd: Versatile Express init failed - -19
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
ALSA device list:#0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 37
input: ImExPS/2 Generic Explorer Mouse as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10007000.kmi/serio1/input/input2
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
EXT4-fs (mmcblk0): recovery complete
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Quota mode: disabled.
VFS: Mounted root (ext4 filesystem) on device 179:0.
Freeing unused kernel image (initmem) memory: 1024K
Run /sbin/init as init process
random: crng init donePlease press Enter to activate this console.
~ # drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
amba 1000f000.wdt: deferred probe pending
amba 10020000.clcd: deferred probe pending
amba 100e0000.memory-controller: deferred probe pending
amba 100e1000.memory-controller: deferred probe pending
amba 100e5000.watchdog: deferred probe pending
i2c 0-0039: deferred probe pending~ # insmod /home/hello.ko
hello: loading out-of-tree module taints kernel.
hello_init : enter~ # rmmod /home/hello.ko
rmmod: remove '/home/hello': No such file or directory
~ # rmmod hello.ko
hello_exit : enter~ # insmod /home/hello.ko
hello_init : enter~ # lsmod
hello 16384 0 - Live 0x7f000000 (O)~ # rmmod hello.ko
hello_exit : enter
~ #
  • 通过验证,hello.ko 可以在 qemu 平台上运行

小结

  • 如果Linux 驱动模块比较小,依赖不多,可以在Linux 内核源码外部编写与编译

  • 使用qemu,开发验证测试一些硬件无关的内核驱动模块,很方便

Linux 内核模块ko在内核源码外部编译的方法相关推荐

  1. v50.03 鸿蒙内核源码分析(编译环境) | 编译鸿蒙防掉坑指南 | 百篇博客分析HarmonyOS源码

    颜渊死.子曰:"噫!天丧予!天丧予!" <论语>:先进篇 百篇博客系列篇.本篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙防掉坑指南 编译构建相关篇 ...

  2. v57.02 鸿蒙内核源码分析(编译过程) | 简单案例说透中间过程 | 百篇博客分析HarmonyOS源码

    子畏于匡,颜渊后.子曰:"吾以女为死矣."曰:"子在,回何敢死?" <论语>:先进篇 百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译 ...

  3. Linux kernel 3.10内核源码分析--进程上下文切换

    一.疑问 进程调度时,当被选中的next进程不是current进程时,需要进行上下文切换. 进行上下文切换时,有一些问题不太容易理解,比如: 1.进程上下文切换必然发生在内核态吗? 2.上下文切换后原 ...

  4. SUSE Linux Enterprise Server 安装内核源码及部署crash调试环境,分析内核崩溃文件(基于sles 15.2)

    实验环境: yg-net-static:~ # uname -a Linux yg-net-static 5.3.18-22-default #1 SMP Wed Jun 3 12:16:43 UTC ...

  5. Linux 网卡驱动sk_buff内核源码随笔

    这几天在调试有关网卡驱动的东西,有很多地方不清楚.有关网卡驱动部分主要有两个很重要的结构体:struct net_device 和struct sk_buff. 驱动大部分都是围绕这两个东西进行操作的 ...

  6. [Linux运维基础]全家桶详解!Linux中RPM包、wget下载、YUM安装、tar包、zip等包管理方式区别与参数详解,附wget下载源码包编译安装方法

    文章目录 一.RPM.tar.gz 1.rpm包格式 2.rpm包管理 3.tar包管理参数 二.wget 1.wget参数 2.wget下载源码包后编译安装 三.YUM 1.YUM工作原理 2. Y ...

  7. Linux kernel 3.10内核源码分析--slab原理及相关代码

    1.基本原理 我们知道,Linux保护模式下,采用分页机制,内核中物理内存使用buddy system(伙伴系统)进行管理,管理的内存单元大小为一页,也就是说使用buddy system分配内存最少需 ...

  8. Linux Kernel 3.10内核源码分析--块设备层request plug/unplug机制

    一.基本原理 Linux块设备层使用了plug/unplug(蓄流/泄流)的机制来提升IO吞吐量.基本原理为:当IO请求提交时,不知直接提交给底层驱动,而是先将其放入一个队列中(相当于水池),待一定时 ...

  9. Linux kernel 3.10内核源码分析--TLB相关--TLB概念、flush、TLB lazy模式

    一.概念及基本原理 TLB即Translation Lookaside Buffer,是MMU中的一种硬件cache,用于缓存页表,即缓存线性地址(虚拟地址)到物理地址的映射关系. 如果没有TLB,那 ...

最新文章

  1. 633. Sum of Square Numbers
  2. android错误-android.util.AndroidRuntimeException:You cannot combine custom titles with other title
  3. Type Casting
  4. mui组件 a 锚点定位(Demo案例演示)- 代码篇
  5. LDA总结 (一) 共轭分布
  6. 12.敏捷估计与规划——Splitting User Stories笔记
  7. [导入]XI 常用的URL
  8. php读取url连接的图片,输出到浏览器
  9. 【转】Java杂谈(四)
  10. oracle 写递归,请问一个递归sql的写法
  11. UC浏览器书签导入Chrome的详解
  12. python调用函数出现未定义_python中函数调用中的“未定义”参数
  13. java对接钉钉发送消息通知
  14. 计算机科学科技创新作品怎么做,第五届科技创新小发明策划书 最终版.doc
  15. 专利解析|多维建模结合AI识别商品特征的方法
  16. 内蒙古大学计算机学院保研到哪些学校,关于2021年推荐优秀应届本科毕业生免试攻读研究生的通知...
  17. 重温C语言三之----指针的认识
  18. 实现Office文档的在线查看等功能
  19. Clusterrolebindings 创建错误
  20. Android系统触摸屏移植后出现小圆圈

热门文章

  1. FM6124D 是一款专为 LED 模块和显示器设计的驱动 IC
  2. Google 测试总监聊如何经营成功的测试职业生涯
  3. Cinemachine API 第三人称跟随案例与参数调节
  4. 视觉与学习青年学者研讨会VALSE 2020线上大会简明日程发布
  5. align-self属性
  6. Task01 数据加载及探索性数据分析
  7. ICANN正式批准成人内容专用域名.xxx
  8. BUUCTF ciscn_2019_c_1
  9. mysql cascade的用法_MySql和Hibernate中关于cascade的用法
  10. Chrome 谷歌浏览器设置系统皮肤UI 和 视频画中画模式