Linux设备驱动开发详解-内核模块一个最简单的内核模块编译、加载、卸载、查看

模块和应用程序的区别

模块

应用程序

init_module 为入口函数

main入口函数

cleanup_module

return

被动调用

主动执行

内核空间

用户空间

系统调用

库函数、系统调用

Printk

printf

权限要求高

权限要求低

源程序

这是一个最简单的内核模块程序,以后的内核程序就是从这里扩展。

// 1. 包含头文件
#include 
//添加模块信息,不加也行
//标明遵循 GPL 协议,
MODULE_LICENSE("GPL");
//模块编写作者信息
MODULE_AUTHOR("yuupengsun, [email protected],185XXXXXXX");
//模块功能描述
MODULE_DESCRIPTION("this a driver for XXXX device");
// 2. 模块入口函数实现 返回值为int 
int init_mymodule(void)
{    //在内核模块编程中 打印函数为 printk()
//  打印输出信息,这个信息只有在控制台 输入命令 dmesg | tail  
	printk("hello, enter mymodule\n");
	return 0;
}
// 3. 模块出口函数实现,返回值必须为void
void exit_mymodule(void)
{   //在内核模块编程中 打印函数为 printk()
//  打印输出信息,这个信息只有在控制台 输入命令 dmesg | tail  
	printk("hello, exit mymodule\n");
}
// 4. 这里是对内核这个内核模块函数的入口声明。
module_init(init_mymodule);
// 5. 这里是对内核模块出口函数的声明
module_exit(exit_mymodule);

Makefile

ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build  
PWD := $(shell pwd)
modules:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
else
  obj-m := mymodule.o
endif

clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*

编译内核模块

linux@ubuntu:$ make
make -C /lib/modules/3.2.0-29-generic-pae/build    M=/home/linux/DriverDemo/module_base modules
make[1]: Entering directory `/usr/src/linux-headers-3.2.0-29-generic-pae'
  CC [M]  /home/linux/DriverDemo/module_base/mymodule.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/linux/DriverDemo/module_base/mymodule.mod.o
  LD [M]  /home/linux/DriverDemo/module_base/mymodule.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.2.0-29-generic-pae'

加载内核模块

linux@ubuntu:$ sudo  insmod  ./mymodule.ko

检查是否已经加载

linux@ubuntu:$ lsmod  |  grep  mymodule   
mymodule                  12421  0   /*这里已经显示我们编译的内核模块已经加载到当前内核中*/

linux@ubuntu:$ dmesg  |  tail /*使用dmesg查看内核打印信息,一般的新加载的内核信息会在最后*/
[   21.007173] ADDRCONF(NETDEV_UP): eth0: link is not ready
[   21.007262] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[   21.415989] init: tftpd-hpa main process (1419) terminated with status 66
[   21.416015] init: tftpd-hpa main process ended, respawning
[   71.494568] audit_printk_skb: 21 callbacks suppressed
[   71.494571] type=1400 audit(1588024692.001:24): apparmor="DENIED" operation="open" parent=1 profile="/usr/lib/telepathy/mission-control-5" name="/usr/share/gvfs/remote-volume-monitors/" pid=3074 comm="mission-control" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[87122.587690] [0]: VMCI: Updating context from (ID=0xffffffff) to (ID=0xb64eaa40) on event (type=0).
[100701.280414] [0]: VMCI: Updating context from (ID=0xb64eaa40) to (ID=0xb64eaa40) on event (type=0).
[139493.831559] [2173]: VMCI: Updating context from (ID=0xb64eaa40) to (ID=0xb64eaa40) on event (type=0).
[155503.674251] hello, enter mymodule  /*这里就是我们的内核模块入口输出信息*/

卸载内核模块

linux@ubuntu:$ sudo rmmod  mymodule /*卸载内核模块*/

linux@ubuntu:~/DriverDemo/module_base$ dmesg | tail  /*使用dmesg查看内核打印输出信息*/
[   21.007262] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[   21.415989] init: tftpd-hpa main process (1419) terminated with status 66
[   21.416015] init: tftpd-hpa main process ended, respawning
[   71.494568] audit_printk_skb: 21 callbacks suppressed
[   71.494571] type=1400 audit(1588024692.001:24): apparmor="DENIED" operation="open" parent=1 profile="/usr/lib/telepathy/mission-control-5" name="/usr/share/gvfs/remote-volume-monitors/" pid=3074 comm="mission-control" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[87122.587690] [0]: VMCI: Updating context from (ID=0xffffffff) to (ID=0xb64eaa40) on event (type=0).
[100701.280414] [0]: VMCI: Updating context from (ID=0xb64eaa40) to (ID=0xb64eaa40) on event (type=0).
[139493.831559] [2173]: VMCI: Updating context from (ID=0xb64eaa40) to (ID=0xb64eaa40) on event (type=0).
[155503.674251] hello, enter mymodule   /*刚刚的内核模块加载输出信息*/
[155605.563102] hello, exit mymodule    /*内核模块退出输出信息*/

linux@ubuntu:$ lsmod  |  grep  mymodule  /*已经卸载了内核模块*/

 

你可能感兴趣的:(linux驱动编程)