Linux 驱动开发之helloworld模块编译、交叉编译

it2023-05-08  74

编译是在本地运行、交叉编译是在嵌入式板卡上运行, 这个两个编译过程的区别仅仅是Makefile的差异。

本文是在Vmware虚拟环境下,Ubuntu系统里进行的测试。

一、创建C文件

首先创建一个空的文件夹,创建hello.c文件,文件内容如下:

#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello, world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit);
二、编写本地运行的Makefile

在编写之前,先确认一下系统的内核源码。

$ uname -r 4.4.0-193-generic

然后看一下系统内建的源码文件。

$ ls /usr/src/ linux-headers-4.4.0-186 linux-headers-4.4.0-190 linux-headers-4.4.0-186-generic linux-headers-4.4.0-190-generic linux-headers-4.4.0-189 linux-headers-4.4.0-193 linux-headers-4.4.0-189-generic linux-headers-4.4.0-193-generic

注意编写Makefile时,采用统一的4.4.0-193-generic版本。 创建Makefile文件,跟hello.c在同一文件夹下,执行: $ vim Makefile

KERNELDIR=/lib/modules/4.4.0-193-generic/build PWD:=$(shell pwd) INSTALLDIR=/home/mgm/work/hello/install obj-m:= hello.o modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: cp hello.ko $(INSTALLDIR) clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions .PHONY: modules modules_install clean

需要注意点:

文件名的第一个M必须大写。命令行都要以tab空格开头。KERNELDIR也可以用下面语句代替 KERNELDIR := /lib/modules/$(shell uname -r)/build 通过shell命令传递内核版本参数。PWD传递的是当前工作路径。-C ( K E R N E L D I R ) 指 明 跳 转 到 源 码 目 录 下 读 取 那 里 的 M a k e f i l e ; M = (KERNELDIR) 指明跳转到源码目录下读取那里的Makefile;M= (KERNELDIR)MakefileM=(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。

保存Makefile,退出后,执行make命令,没有问题的话会出现如下信息:

# make make -C /lib/modules/4.4.0-193-generic/build M=/home/work/hello modules make[1]: Entering directory '/usr/src/linux-headers-4.4.0-193-generic' Building modules, stage 2. MODPOST 1 modules make[1]: Leaving directory '/usr/src/linux-headers-4.4.0-193-generic'

执行模块加载命令

insmod ./hello.ko

然后执行卸载命令

rmmod hello.ko

这里实验是用的虚拟机,在仿真器中运行insmod和rmmod,是不会在屏幕上看到任何输出的。实际上它可能输出到系统日志文件中的,例如/var/log/message,打开message,定位到最后,就会看到输出的消息。

# cat /var/log/kern.log | tail -2 Oct 20 01:09:17 ubuntu kernel: [108198.793234] Hello world Oct 20 01:09:30 ubuntu kernel: [108212.185816] Goodbye, cruel world
三、编写嵌入式系统运行的Makefile

在进行交叉编译驱动模块编写之前,需要先确保嵌入式系统运行的linux源码在主机环境中是可以被正确交叉编译的。

在工作目录下创建一个空白文件夹,创建hello.c 源程序,可以复制上面例子中的代码。 然后在同目录下创建Makefile文件 执行 $vim Makefile 输入

ifneq ($(KERNELRELEASE),) obj-m:= hello.o else KDIR := /home/mgm/opt/freescale/imx6/linux-4.1.15 PWD := $(shell pwd) CROSS_COMPILE=arm-poky-linux-gnueabi- CC =$(CROSS_COMPILE)gcc all: make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) modules clean: rm *.o *.ko *.mod.c endif

这一行KDIR := /home/mgm/opt/freescale/imx6/linux-4.1.15 需要换成自己的路径, 编译器CROSS_COMPILE=arm-poky-linux-gnueabi-也要根据自己的工具设置。

编译前可以测试一下编译器

$ arm-poky-linux-gnueabi-gcc -v

正常的话会打印很多行编译器信息。

然后执行编译

$ make

编译后的信息

$ make make -C /home/serana/imx6/linux-4.1.15 M=/home/serana/imx6/test ARCH=arm CROSS_COMPILE=arm-poky-linux-gnueabi- modules make[1]: Entering directory `/home/serana/imx6/linux-4.1.15' CC [M] /home/serana/imx6/test/hello.o Building modules, stage 2. MODPOST 1 modules CC /home/serana/imx6/test/hello.mod.o LD [M] /home/serana/imx6/test/hello.ko make[1]: Leaving directory `/home/serana/imx6/linux-4.1.15'

把编译好的模块下载到目标板上后,执行

# insmod ./hello.ko

PASS !

最新回复(0)