【Linux】驱动.ko文件编写加载

参考

一、.ko 文件介绍

.ko文件是kernel object文件(内核模块),该文件的意义就是把内核的一些功能移动到内核外边, 需要的时候插入内核,不需要时卸载。

二、优点

(1)这样可以缩小内核体积;

(2)使用方便。

三、.ko文件一般的用处

(1)作为一个功能模块,需要使用时,直接插入运行就行。如在imx6上连接模拟摄像头,先运行模拟摄像头对应的驱动模块 camera.ko文件,然后对应的工程执行文件运行就行。

四、使用.ko 文件
1、加载驱动模块test.ko

(1)方法一
进入test.ko驱动模块文件所在的目录,然后直接 insmod test.ko

(2)方法二
将test.ko文件拷贝到/lib/module/#uname-r#/目录下,这里,#uname -r#意思是,在终端中输入
uname -r后显示的内核版本及名称,例如我的环境centos 7系统下#uname-r#就是3.10.0-957.12.2.el7.x86_64然后 depmod(会在/lib/modules/#uname -r#/目录下生成modules.dep和modules.dep.bb文件,表明模块的依赖关系)
最后 modprobe test(注意这里无需输入.ko后缀) 即可

注:两种方法的区别

modprobe和insmod类似,都是用来动态加载驱动模块的,区别在于modprobe可以解决load module时的依赖关系,它是通过/lib/modules/#uname -r/modules.dep(.bb)文件来查找依赖关系的;而insmod不能解决依赖问题。也就是说,如果你确定你要加载的驱动模块不依赖其他驱动模块的话,既可以insmod也可以modprobe,当然insmod可以在任何目录下执行,更方便一些。而如果你要加载的驱动模块还依赖其他ko驱动模块的话,就只能将模块拷贝到上述的特定目录,depmod后再modprobe。

2、查看已加载的驱动模块列表

在任何目录下输入命令lsmod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
`[root@HikvisionOS ~]# lsmod` 
`Module Size Used by`
`ip6t_rpfilter 12595 1`
`ipt_REJECT 12541 2`
`nf_reject_ipv4 13373 1 ipt_REJECT`
`ip6t_REJECT 12625 2`
`nf_reject_ipv6 13717 1 ip6t_REJECT`
`xt_conntrack 12760 19`
`ip_set 45644 0`
`nfnetlink 14490 1 ip_set`
`ebtable_nat 12807 1`
`ebtable_broute 12731 1`
`bridge 151336 1 ebtable_broute`
`stp 12976 1 bridge`
`llc 14552 2 stp,bridge`
`ip6table_nat 12864 1`
`nf_conntrack_ipv6 18935 11`
`nf_defrag_ipv6 35104 1 nf_conntrack_ipv6`
`nf_nat_ipv6 14131 1 ip6table_nat`
`ip6table_mangle 12700 1`
`ip6table_security 12710 1`
`ip6table_raw 12683 1`
`iptable_nat 12875 1`
`nf_conntrack_ipv4 15053 10`
`nf_defrag_ipv4 12729 1 nf_conntrack_ipv4`
3、卸载驱动模块

在任何目录下, 输入命令

rmmod注:“module_name”是lsmod显示的模块名称,而不是对应的ko文件名

五、编写生成.ko 文件

Linux下hello.ko内核模块制作的全过程

1.linux系统用的是Redflag 6.0 SP1 下载地址:ftp://ftp.redflag-linux.com/pub/redflag/dt6sp1/SP1/redflag-6-sp1.iso, 系统安装很容易,安提示做就好。
所用的内核源码目录树下载地址:ftp://ftp.redflag-linux.com/pub/redflag/dt6sp1/SP1/redflag-6-tool-sp1-src1.iso,将此iso文件挂载到/mnt下,安装其中的内核rpm包。
挂载方法:mount -t iso9660 redflag-6-tool-sp1-src1.iso /mnt/ -o loop
内核目录树安装方法:cd /mnt/RedFlag/SRMPS/

rpm -i kernel-2.6.23.1-4.src.rpm

2.编写hello模块代码,源码如下:

hello.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <linux/init.h>  
#include <linux/module.h>

MODULE_LICENSE("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);

3.编写hello模块的Makefile文件,Makefile内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
Makefile

#Makefile 2.6

obj-m :=hello.o
KERNEL :=/usr/src/kernels/$(uname -r)/
PWD :=$(shell pwd)
modules :
$(MAKE) -C $(KERNEL) M=$(PWD) modules
.PHONEY:clean
clean :
rm -f *.o *.ko

4.编译模块
在命令行进入hello.c所在的文件夹下执行make命令即可完成hello模块的编译。用ls命令可以查看到hello.ko文件,此文件就是我们自定义的内核模块。

5.安装hello模块

命令行下执行命令:insmod hello.ko 。通过命令:cat /var/log/messages

可以看到下面这样的信息:“Aug 6 13:37:59 localhost kernel: Hello, world”,说明模块加载成功了。

6.另外一种模块Makefile的编写方法

Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# If KERNELRELEASE is defined, we've been invoked from the  

# kernel build system and can use its language.

ifneq ($(KERNELRELEASE),)

obj-m := hello.o

# Otherwise we were called directly from the command

# line; invoke the kernel build system.

else

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

endif
  1. 卸载hello模块

命令行下执行命令:rmmod hello.ko即可。通过命令:cat /var/log/messages.
可以看到下面这样的信息:“Aug 6 13:40:36 localhost kernel: Goodbye, cruel world”,说明模块卸载成功。

  1. 查看模块信息

命令行下执行命令:modinfo hello
————————————————
版权声明:本文为CSDN博主「worthsen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38880380/article/details/79227760