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

编译是在本地运行、交叉编译是在嵌入式板卡上运行,
这个两个编译过程的区别仅仅是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

需要注意点:

  1. 文件名的第一个M必须大写。
  2. 命令行都要以tab空格开头。
  3. KERNELDIR也可以用下面语句代替
    KERNELDIR := /lib/modules/$(shell uname -r)/build
    通过shell命令传递内核版本参数。
  4. PWD传递的是当前工作路径。
  5. -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 !

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值