linux驱动:编写最简单的内核模块helloWorld并移植到ARM板

环境:主机-Ubuntu 16.04,开发板-友善之臂tiny4412开发板,内核版本linux-3.5

参考《Linux设备驱动开发详解 基于最新的Linux 4.0内核》(宋宝华 编著)

 

一、简介

一个Linux内核模块主要由以下几部分组成:

1、模块加载函数

当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。

2、模块卸载函数

当通过rmmod命令卸载模块时,模块的卸载函数会自动被内核执行,完成与模块加载函数相反的功能。

3、模块许可证

许可证(LINCESE)声明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染(Kernel Tainted)的警告。在Linux内核模块领域,可接受的LICENSE包括”GPL“、"GPL v2"、"GPL and additional rights" ...等。

4、模块参数(可选)

模块参数是模块被加载的时候可以传递给它的值,它本身对应模块内部的全局变量。

5、模块导出符号(可选)

内核模块可以导出的符号(symbol,对应于函数或变量),若导出,其他模块则可以使用本模块的变量或函数。

6、模块作者等信息声明(可选)

 

 

二、模块实现

代码:

#include <linux/init.h>
#include <linux/module.h>

int __init hello_init(void)
{
	printk("Hello World enter ++\n");
	return 0;
}

void __exit hello_exit(void)
{
	printk("Hello world exit --\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_AUTHOR("https://blog.csdn.net/qq_30155503");
MODULE_LICENSE("GPL v2");

1、加载:Linux内核模块加载函数一般以"__init"标识声明,如“int __init hello_init(void)”函数;通过module_init()函数指定加载函数,如“module_init(hello_init);”,指定加载函数为hello_init();当通过insmod或modprobe命令加载内核模块时,hello_init()将被自动执行;

2、卸载:Linux内核模块加载函数一般以"__exit"标识声明,如“void __exit hello_exit(void)”函数;通过module_exit()函数指定卸载函数,如“module_exit(hello_exit);”,指定卸载函数为hello_exit();当通过rmmod命令卸载模块时,hello_exit()将被自动执行。

3、MODULE_AUTHOR();是作者信息,MODULE_LICENSE();是模块许可证声明。

通常,加载函数完成初始化工作、申请资源等,卸载函数则完成释放资源、去初始化工作;两者的功能是相反的。

 

三、Makefile编写及编译

Makefile代码:

# to build modules

obj-m := hello.o

KERNELDIR ?= /data/arm-linux/kernel/tiny4412/linux-3.5
PWD := $(shell pwd)

all: modules

modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
	rm -rf *.o *.ko *mod* *.sy* *ord* .*cmd .tmp*

注释:

obj-m:表示编译成模块,obj-y表示编译进内核。

KERNELDIR:内核源码的路径,编译与运行环境的内核版本应一致,即与ARM板上跑的linux系统的版本一致,“?=”表示若为空则为之赋值。(此处我指定的路径为tiny4412开发板附带的3.5版本内核)

当执行make clean时,当清除make时所生成的所有文件。

 

编译:make

错误信息:

  ERROR: Kernel configuration is invalid.
         include/generated/autoconf.h or include/config/auto.conf are missing.
         Run 'make oldconfig && make prepare' on kernel src to fix it.

原因:内核没有编译好,要先编译成功内核才要用,提示你运行“make oldconfig && make prepare”,最终可行的执行如下:

make oldconfig && make prepare && make scripts

编译通过:

make -C /data/arm-linux/kernel/tiny4412/linux-3.5 M=/data/project/driver/hello modules
make[1]: Entering directory '/data/arm-linux/kernel/tiny4412/linux-3.5'
  CC [M]  /data/project/driver/hello/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /data/project/driver/hello/hello.mod.o
  LD [M]  /data/project/driver/hello/hello.ko
make[1]: Leaving directory '/data/arm-linux/kernel/tiny4412/linux-3.5'

在当前目录生成了内核模块文件 hello.ko

 

四、运行

首先,将生成的内核模块文件hello.ko移到开发板上

1、加载模块:执行insmod命令进行加载


[root@FriendlyARM /mnt]# ls 
hello.ko
[root@FriendlyARM /mnt]# insmod hello.ko 
[  909.890000] Hello World enter ++

 

2、查看模块:执行命令lsmod可查看当前加载的内核模块


[root@FriendlyARM /mnt]# lsmod 
hello 570 0 - Live 0xbf278000 (O)
libertas_sdio 8423 0 [permanent], Live 0xbf25a000 (O)
libertas 54371 1 libertas_sdio,[permanent], Live 0xbf247000 (O)
zd1211rw 44215 0 [permanent], Live 0xbf237000 (O)
rt2800usb 12324 0 [permanent], Live 0xbf22f000 (O)

可见,确实有hello模块存在。

 

3、卸载模块:执行rmmod命令进行卸载


[root@FriendlyARM /mnt]# rmmod hello
[  976.995000] Hello world exit --

注意:加载时的参数是文件名("xxx.ko"),卸载时是模块名("hello")。

 

由上可见,加载、卸载模块时确实是自动执行了指定的加载函数与卸载函数。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux设备驱动程序学习(0)-Hello, world!模块 Linux设备驱动程序学习(0) -Hello, world!模块 一个学习Linux设备驱动程序都会碰到的第一个例程: #include #include MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello, Tekkaman Ninja !\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, Tekkaman Ninja !\n Love Linux !Love ARM ! Love KeKe !\n"); } module_init(hello_init); module_exit(hello_exit); 我将其复制到我的工作目录,并编写了一个简单的Makefile文件: KERNELDIR = /home/tekkaman/working/SBC2440/linux-2.6.22.2 # The current directory is passed to sub-makes as argument PWD := $(shell pwd) INSTALLDIR = /home/tekkaman/working/rootfs/lib/modules CROSS_COMPILE =/home/tekkaman/working/crosstool-gcc410-k26222/gcc-4.1.0-glibc-2.3.2/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu- CC = $(CROSS_COMPILE)gcc 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 说实话,以上是我参考了《Linux设备驱动程序(第3版)》的Makefile源码修改得来的。我对Makefile不是很了解,是该好好学习学习了! 然后就是make modules 、 make modules_install 。 [root@Tekkaman-Ninja Helloworld]# make modules make -C /home/tekkaman/working/SBC2440/linux-2.6.22.2 M=/home/tekkaman/working/Linuxdriver/Helloworld modules make[1]: Entering directory `/home/tekkaman/working/SBC2440/linux-2.6.22.2' CC [M] /home/tekkaman/working/Linuxdriver/Helloworld/hello.o Building modules, stage 2. MODPOST 1 modules CC /home/tekkaman/working/Linuxdriver/Helloworld/hello.mod.o LD [M] /home/tekkaman/working/Linuxdriver/Helloworld/hello.ko make[1]: Leaving directory `/home/tekkaman/working/SBC2440/linux-2.6.22.2' [root@Tekkaman-Ninja Helloworld]# make modules_install cp hello.ko /home/tekkaman/working/rootfs/lib/modules [root@Tekkaman-Ninja Helloworld]# 在我的开发上的操作: [Tekkaman2440@SBC2440V4]#cd /lib/modules/ [Tekkaman2440@SBC2440V4]#ls cs89x0.ko hello.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值