编译驱动的内核源码-Linux驱动开发(一):最简单的内核驱动

1.编写一个.c程序

编译DriverFramework.c。 这个模块功能简单,就是在被内核加载的时候复制“helloinit”,在被内核卸载的时候复制“helloexit”。

#include 
#include 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zz"); //作者名称,可以随意命名
static int hello_init(void)
{
	printk("hello initn");
	return 0;
}
static void hello_exit(void)
{
	printk("hello exitn");
	return;
}
module_init(hello_init);
module_exit(hello_exit);

我们通常接触到的经典C程序应用程序运行用户空间,但在本例中,它们是驱动程序编译驱动的内核源码,运行在内核空间。

当我们在终端输入insmod命令时,module_init将被调用。 它和module_exit都是在linux/init.h中定义的宏。 module_init会将内核模块加载函数声明为hello_init(函数名可以任意定义)。 hello_init函数的作用是复制内核日志中的“helloinit”。

同样,当在终端中输入 rmmod 命令时,将调用 module_exit 宏。 module_exit 会将内核模块卸载函数声明为 hello_exit 函数。 该函数的作用是复制内核日志中的“helloexit”。

编译驱动的内核源码-Linux驱动开发(一):最简单的内核驱动

宏MODULE_LICENSE用于声明该模块的许可证。 该模块符合 GPL 合同。 否则,加载此模块时您将收到“kerneltainted”警告

宏 MODULE_AUTHOR 用于声明作者。

printk函数是一个复制函数,运行在内核态,而printf函数运行在用户态。

2. 编写Makefile

ifneq ($(KERNELRELEASE),)
	obj-m:=DriverFramework.o
else
	KDIR	:= /lib/modules/$(shell uname -r)/build
	PWD		:= $(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	make -C $(KDIR) M=$(PWD) clean
endif

解释一下Makefile。 KERNELRELEASE 是在内核源代码底层 Makefile 中定义的变量。 当模块未导入内核源代码时,不会定义该变量。 模块连接到内核源代码后,定义该变量。

KDIR变量代表目录存放的是该版本Linux内核的源代码,其中调用的shell命令uname -r用于复制内核的版本号。 PWD是当前目录所在的路径

在终端输入make命令后,编译.c文件。 这个过程比较复杂。首先编译驱动的内核源码初始编译前变量KERNELRELEASE为空,因此执行else旁边的程序,即

make -C $(KDIR) M=$(PWD) modules

-C参数的作用是指定跳转目录。 -C$(KDIR) 指定跳转到内核源代码所在目录并读取那里的Makefile以启动kbuild机制。 M=$(PWD) 然后返回当前目录继续执行当前Makefile。

kbuild即kernelbuild,用于编译Linux内核文件,并对Makefile进行功能扩展。 内核中大部分Makefile都是使用kbuild来组织的,这样可以让之前的Makefile代码更加简洁高效。 kbuild中预定义了一些变量,例如obj-y和obj-m,用于指定要生成的.o目标文件。 只要变量被正式参数化,kbuild就会手动将代码编译到内核或模块中。

一般内核驱动的编译加载有两种形式:第一种是直接将驱动编译到内核中,对应obj-y变量;第二种是直接将驱动编译到内核中,对应obj-y变量; 第二种是将驱动程序作为模块单独编译成.ko文件,而不进行编译。 进入内核然后自动加载,即obj-m变量。 本例中,将DriverFramework.o形参传递给obj-m变量使用第二种模式生成独立的DriverFramework.ko文件。

3.模块编译与加载

首先使用 make 编译模块。

接下来介绍一下需要在终端输入的命令。首先加载驱动模块,命令为

sudo insmod DriverFramework.ko

注意insmod命令只能在root权限下执行。

编译驱动的内核源码-Linux驱动开发(一):最简单的内核驱动

复制内核信息

dmesg

如果您认为内核复制了太多信息,可以使用 dmesg -c 清除内核日志,然后加载模块。

可以看到helloinit已经被复制了。

使用 lsmod 查看所有加载的模块。 其实我们也可以使用下面的命令来只查看我们感兴趣的模块。

lsmod | grep DriverFramework

删除内核模块的说明

sudo rmmod DriverFramework

查看内核拷贝信息。 可以看到helloexit已经被复制了。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 源码编译 编译驱动的内核源码-Linux驱动开发(一):最简单的内核驱动 https://www.wkzy.net/game/201497.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务