AI智能
改变未来

Linux内核模块驱动加载与dmesg调试

  因为近期用到了Linux内核的相关知识,下面随笔将给出内核模块的编写记录,供大家参考。

1、运行环境

  Ubuntu版本:20.04

  Linux内核版本:5.4.0-42-generic

  gcc版本:gcc version 9.3.0

  驱动和一般应用程序的执行方式很大不同

2、内核模块模型说明

(1)驱动和一般应用程序的执行方式很大不同

  一般应用由main函数开始执行,流程基本由程序自身控制

  驱动程序没有main函数,由回调方式驱动运行

(2)回调方式:

  先向内核注册函数,然后应用程序触发这些函数的执行

  例如:驱动程序在初始化时,向内核注册处理某个设备写操作的函数

  当应用程序使用write系统调用写该设备时,内核就会调用注册的上述函数

3、内核模型常见的回调函数举例

(1)DriverInitialize

  驱动初始化函数,通过宏静态注册;

  $ insmod PrintModule.ko,安装驱动并触发该函数,通常会创建设备对象;

(2)DriverUninitialize

  驱动销毁函数,通过宏静态注册;

  $ rmmod PrintModule,卸载驱动并触发该函数;

(3)DriverOpen

  打开设备函数,动态注册;

  应用调用open函数打开设备对象时,会触发该函数;

(4)DriverRead

  读设备函数,动态注册;

  应用调用read函数读设备时,会触发该函数;

(5)DriverWrite

  写设备函数,动态注册;

  应用调用write函数写设备时,会触发该函数;

(7)DriverIOControl

  设备控制函数,动态注册;

  应用调用ioctl函数操作设备时,会触发该函数;

(8)DriverMMap

  设备内存映射函数,动态注册;

  应用调用mmap函数时,会触发该函数;

下面给出驱动模块编写函数:

4、DriverMain.c

1 #include \"DriverMain.h\"23 #include \"DriverFileOperations.h\"45 #include \"ToolFunctions.h\"6789 MODULE_LICENSE(\"Dual BSD/GPL\");10111213 struct SLDriverParameters gsl56cDriverParameters = {0};14151617 struct file_operations gslNvmDriverFileOperations =1819 {2021     .owner = THIS_MODULE,2223     .open  = DriverOpen,2425     .release = DriverClose,2627     .read  = DriverRead,2829     .write = DriverWrite,3031     .unlocked_ioctl = DriverIOControl,3233     .mmap = DriverMMap,3435 };36373839 int InitalizeCharDevice(void)4041 {4243     int result;4445     struct device *pdevice;46474849     result = alloc_chrdev_region(&(gslDriverParameters.uiDeviceNumber), 0, 1, DEVICE_NAME);5051     if(result < 0)5253     {5455         printk(KERN_ALERT DEVICE_NAME \" alloc_chrdev_region error\\n\");5657         return result;5859     }60616263     gslDriverParameters.pslDriverClass = class_create(THIS_MODULE, DEVICE_NAME);6465     if(IS_ERR(gslDriverParameters.pslDriverClass))6667     {6869         printk(KERN_ALERT DEVICE_NAME \" class_create error\\n\");70717273         result = PTR_ERR(gslDriverParameters.pslDriverClass);7475         goto CLASS_CREATE_ERROR;7677     }78798081     cdev_init(&(gslDriverParameters.slCharDevice), &gslNvmDriverFileOperations);8283     gslDriverParameters.slCharDevice.owner = THIS_MODULE;84858687     result = cdev_add(&(gslDriverParameters.slCharDevice), gslDriverParameters.uiDeviceNumber, 1);8889     if(result < 0)9091     {9293         printk(KERN_ALERT DEVICE_NAME \" cdev_add error\\n\");9495         goto CDEV_ADD_ERROR;9697     }9899100101     pdevice = device_create(gslDriverParameters.pslDriverClass, NULL, gslDriverParameters.uiDeviceNumber, NULL, DEVICE_NAME);102103     if(IS_ERR(pdevice))104105     {106107         printk(KERN_ALERT DEVICE_NAME \" device_create error\\n\");108109110111         result = PTR_ERR(pdevice);112113         goto DEVICE_CREATE_ERROR;114115     }116117118119     return 0;120121122123 DEVICE_CREATE_ERROR:124125     cdev_del(&(gslDriverParameters.slCharDevice));126127128129 CDEV_ADD_ERROR:130131     class_destroy(gslDriverParameters.pslDriverClass);132133134135 CLASS_CREATE_ERROR:136137     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);138139140141     return result;142143 }144145146147 void UninitialCharDevice(void)148149 {150151     device_destroy(gslDriverParameters.pslDriverClass, gslDriverParameters.uiDeviceNumber);152153154155     cdev_del(&(gslDriverParameters.slCharDevice));156157158159     class_destroy(gslDriverParameters.pslDriverClass);160161162163     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);164165 }166167168169 static int DriverInitialize(void)170171 {172173     DEBUG_PRINT(DEVICE_NAME \" Initialize\\n\");174175176177     return InitalizeCharDevice();178179 }180181182183 static void DriverUninitialize(void)184185 {186187     DEBUG_PRINT(DEVICE_NAME \" Uninitialize\\n\");188189190191     UninitialCharDevice();192193 }194195196197 module_init(DriverInitialize);198199 module_exit(DriverUninitialize);

5、DriverMain.h

1 #ifndef DriverMain_H23 #define DriverMain_H4567 #include <linux/init.h>89 #include <linux/module.h>1011 #include <asm/mtrr.h>1213 #include <linux/device.h>1415 #include <linux/mm.h>1617 #include <linux/cdev.h>1819 #include <linux/slab.h>20212223 #define DEVICE_NAME \"msg_printer\"24252627 struct SLDriverParameters2829 {3031     struct class *pslDriverClass;3233     dev_t uiDeviceNumber;3435     struct cdev slCharDevice;3637 };38394041 extern struct SLDriverParameters gslDriverParameters;42434445 #endif

6、DriverFileOperations.c

1 #include \"DriverMain.h\"23 #include \"DriverFileOperations.h\"45 #include \"ToolFunctions.h\"6789 MODULE_LICENSE(\"Dual BSD/GPL\");10111213 struct SLDriverParameters gslDriverParameters = {0};14151617 struct file_ad8operations gslNvmDriverFileOperations =1819 {2021     .owner = THIS_MODULE,2223     .open  = DriverOpen,2425     .release = DriverClose,2627     .read  = DriverRead,2829     .write = DriverWrite,3031     .unlocked_ioctl = DriverIOControl,3233     .mmap = DriverMMap,3435 };36373839 int InitalizeCharDevice(void)4041 {4243     int result;4445     struct device *pdevice;46474849     result = alloc_chrdev_region(&(gslDriverParameters.uiDeviceNumber), 0, 1, DEVICE_NAME);5051     if(result < 0)5253     {5455         printk(KERN_ALERT DEVICE_NAME \" alloc_chrdev_region error\\n\");5657         return result;5859     }60616263     gslDriverParameters.pslDriverClass = class_create(THIS_MODULE, DEVICE_NAME);6465     if(IS_ERR(gslDriverParameters.pslDriverClass))6667     {6869         printk(KERN_ALERT DEVICE_NAME \" class_create error\\n\");70717273         result = PTR_ERR(gslDriverParameters.pslDriverClass);7475         goto CLASS_CREATE_ERROR;7677     }78798081     cdev_init(&(gslDriverParameters.slCharDevice), &gslNvmDriverFileOperations);8283     gslDriverParameters.slCharDevice.owner = THIS_MODULE;84858687     result = cdev_add(&(gslDriverParameters.slCharDevice), gslDriverParameters.uiDeviceNumber, 1);8889     if(result < 0)9091     {9293         printk(KERN_ALERT DEVICE_NAME \" cdev_add error\\n\");9495         goto CDEV_ADD_ERROR;9697     }9899100101     pdevice = device_create(gslDriverParameters.pslDriverClass, NULL, gslDriverParameters.uiDeviceNumber, NULL, DEVICE_NAME);102103     if(IS_ERR(pdevice))104105     {106107         printk(KERN_ALERT DEVICE_NAME \" device_create error\\n\");108109110111         result = PTR_ERR(pdevice);112113         goto DEVICE_CREATE_ERROR;114115     }116117118119     return 0;120121122123 DEVICE_CREATE_ERROR:124125     cdev_del(&(gslDriverParameters.slCharDevice));126127128129 CDEV_ADD_ERROR:130131     class_destroy(gslDriverParameters.pslDriverClass);132133134135 CLASS_CREATE_ERROR:136137     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);138139140141     return result;142143 }144145146147 void UninitialCharDevice(void)148149 {150151     device_destroy(gslDriverParameters.pslDriverClass, gslDriverParameters.uiDeviceNumber);152153154155     cdev_del(&(gslDriverParameters.slCharDevice));156157158159     class_destroy(gslDriverParameters.pslDriverClass);160161162163     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);164165 }166167168169 static int DriverInitialize(void)170171 {172173     DEBUG_PRINT(DEVICE_NAME \" Initialize\\n\");174175176177     return InitalizeCharDevice();178179 }180181182183 static void DriverUninitialize(void)184185 {186187     DEBUG_PRINT(DEVICE_NAME \" Uninitialize\\n\");ad8188189190191     UninitialCharDevice();192193 }194195196197 module_init(DriverInitialize);198199 module_exit(DriverUninitialize);

7、DriverFileOperations.h

1 #ifndef DriverFileOperations_H23 #define DriverFileOperations_H45 int DriverOpen(struct inode *pslINode, struct file *pslFileStruct)67 int DriverClose(struct inode *pslINode, struct file *pslFileStruct);89 ssize_t DriverRead(struct file *pslFileStruct, char __user *pBuffer, size_t nCount, loff_t *pOffset);1011 ssize_t DriverWrite(struct file *pslFileStruct, const char __user *pBuffer, size_t nCount, loff_t *pOffset);1213 long DriverIOControl(struct file *pslFileStruct, unsigned int uiCmd, unsigned long ulArg);1415 int DriverMMap(struct file *pslFileStruct, struct vm_area_struct *pslVirtualMemoryArea);1617 #endif

8、编译内核模块的MakeFile文件:

1 ifneq ($(KERNELRELEASE),)23     obj-m := PrintModule.o45     PrintModule-objs := DriverMain.o DriverFileOperations.o67 EXTRA_CFLAGS := -DTEST_DEBUG -ggdb -O089 else1011     KERNELDIR ?= /lib/modules/$(shell uname -r)/build1213     PWD := $(shell pwd)1415 default:1617     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules1819     rm *.ord1044er *.symvers *.mod.c *.o .*.o.cmd .*.cmd .tmp_versions -rf2021 endif

9、运行测试

  首先运行MakeFile文件,通过终端输入make命令即可,生成PrintModule.ko和PrintModule.mod:

  之后加载内核驱动,通过输入$ sudo insmod PrintModule.ko命令,之后查看dmesg查看驱动信息(也可通过输出调试信息的函数printk来进行调试),具体如下:

  随之通过输入$ sudo rmmod PrintModule命令来卸载驱动,也是通过dmesg来查看内核驱动信息(也可通过输出调试信息的函数printk来进行调试):

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Linux内核模块驱动加载与dmesg调试