前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux内核模块驱动加载与dmesg调试

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

作者头像
玖柒的小窝
修改2021-09-15 11:39:31
6.5K0
修改2021-09-15 11:39:31
举报
文章被收录于专栏:各类技术文章~各类技术文章~

因为近期用到了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

C++

代码语言:javascript
复制
  1 #include "DriverMain.h"
  2 
  3 #include "DriverFileOperations.h"
  4 
  5 #include "ToolFunctions.h"
  6 
  7 
  8 
  9 MODULE_LICENSE("Dual BSD/GPL");
 10 
 11 
 12 
 13 struct SLDriverParameters gslDriverParameters = {0};
 14 
 15 
 16 
 17 struct file_operations gslNvmDriverFileOperations = 
 18 
 19 {
 20 
 21     .owner = THIS_MODULE,
 22 
 23     .open  = DriverOpen,
 24 
 25     .release = DriverClose,
 26 
 27     .read  = DriverRead,
 28 
 29     .write = DriverWrite,
 30 
 31     .unlocked_ioctl = DriverIOControl,
 32 
 33     .mmap = DriverMMap,
 34 
 35 };
 36 
 37 
 38 
 39 int InitalizeCharDevice(void)
 40 
 41 {
 42 
 43     int result;
 44 
 45     struct device *pdevice;
 46 
 47 
 48 
 49     result = alloc_chrdev_region(&(gslDriverParameters.uiDeviceNumber), 0, 1, DEVICE_NAME);
 50 
 51     if(result < 0)
 52 
 53     {
 54 
 55         printk(KERN_ALERT DEVICE_NAME " alloc_chrdev_region error\n");
 56 
 57         return result;
 58 
 59     }
 60 
 61 
 62 
 63     gslDriverParameters.pslDriverClass = class_create(THIS_MODULE, DEVICE_NAME);
 64 
 65     if(IS_ERR(gslDriverParameters.pslDriverClass)) 
 66 
 67     {
 68 
 69         printk(KERN_ALERT DEVICE_NAME " class_create error\n");
 70 
 71 
 72 
 73         result = PTR_ERR(gslDriverParameters.pslDriverClass);
 74 
 75         goto CLASS_CREATE_ERROR;
 76 
 77     }
 78 
 79 
 80 
 81     cdev_init(&(gslDriverParameters.slCharDevice), &gslNvmDriverFileOperations);
 82 
 83     gslDriverParameters.slCharDevice.owner = THIS_MODULE;
 84 
 85 
 86 
 87     result = cdev_add(&(gslDriverParameters.slCharDevice), gslDriverParameters.uiDeviceNumber, 1);
 88 
 89     if(result < 0) 
 90 
 91     {
 92 
 93         printk(KERN_ALERT DEVICE_NAME " cdev_add error\n");
 94 
 95         goto CDEV_ADD_ERROR;
 96 
 97     }
 98 
 99 
100 
101     pdevice = device_create(gslDriverParameters.pslDriverClass, NULL, gslDriverParameters.uiDeviceNumber, NULL, DEVICE_NAME);
102 
103     if(IS_ERR(pdevice)) 
104 
105     {
106 
107         printk(KERN_ALERT DEVICE_NAME " device_create error\n");
108 
109 
110 
111         result = PTR_ERR(pdevice);
112 
113         goto DEVICE_CREATE_ERROR;
114 
115     }
116 
117 
118 
119     return 0;
120 
121 
122 
123 DEVICE_CREATE_ERROR:
124 
125     cdev_del(&(gslDriverParameters.slCharDevice));
126 
127 
128 
129 CDEV_ADD_ERROR:
130 
131     class_destroy(gslDriverParameters.pslDriverClass);
132 
133 
134 
135 CLASS_CREATE_ERROR:
136 
137     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);
138 
139 
140 
141     return result;
142 
143 }
144 
145 
146 
147 void UninitialCharDevice(void)
148 
149 {
150 
151     device_destroy(gslDriverParameters.pslDriverClass, gslDriverParameters.uiDeviceNumber);
152 
153 
154 
155     cdev_del(&(gslDriverParameters.slCharDevice));
156 
157 
158 
159     class_destroy(gslDriverParameters.pslDriverClass);
160 
161 
162 
163     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);
164 
165 }
166 
167 
168 
169 static int DriverInitialize(void)
170 
171 {
172 
173     DEBUG_PRINT(DEVICE_NAME " Initialize\n");
174 
175 
176 
177     return InitalizeCharDevice();
178 
179 }
180 
181 
182 
183 static void DriverUninitialize(void)
184 
185 {
186 
187     DEBUG_PRINT(DEVICE_NAME " Uninitialize\n");
188 
189 
190 
191     UninitialCharDevice();
192 
193 }
194 
195 
196 
197 module_init(DriverInitialize);
198 
199 module_exit(DriverUninitialize);

5、DriverMain.h

C++

代码语言:javascript
复制
 1 #ifndef DriverMain_H
 2 
 3 #define DriverMain_H
 4 
 5 
 6 
 7 #include <linux/init.h>
 8 
 9 #include <linux/module.h>
10 
11 #include <asm/mtrr.h>
12 
13 #include <linux/device.h>
14 
15 #include <linux/mm.h>
16 
17 #include <linux/cdev.h>
18 
19 #include <linux/slab.h>
20 
21 
22 
23 #define DEVICE_NAME "msg_printer"
24 
25 
26 
27 struct SLDriverParameters
28 
29 {
30 
31     struct class *pslDriverClass;
32 
33     dev_t uiDeviceNumber;
34 
35     struct cdev slCharDevice;
36 
37 };
38 
39 
40 
41 extern struct SLDriverParameters gslDriverParameters;
42 
43 
44 
45 #endif

6、DriverFileOperations.c

C++

代码语言:javascript
复制
  1 #include "DriverMain.h"
  2 
  3 #include "DriverFileOperations.h"
  4 
  5 #include "ToolFunctions.h"
  6 
  7 
  8 
  9 MODULE_LICENSE("Dual BSD/GPL");
 10 
 11 
 12 
 13 struct SLDriverParameters gslDriverParameters = {0};
 14 
 15 
 16 
 17 struct file_operations gslNvmDriverFileOperations = 
 18 
 19 {
 20 
 21     .owner = THIS_MODULE,
 22 
 23     .open  = DriverOpen,
 24 
 25     .release = DriverClose,
 26 
 27     .read  = DriverRead,
 28 
 29     .write = DriverWrite,
 30 
 31     .unlocked_ioctl = DriverIOControl,
 32 
 33     .mmap = DriverMMap,
 34 
 35 };
 36 
 37 
 38 
 39 int InitalizeCharDevice(void)
 40 
 41 {
 42 
 43     int result;
 44 
 45     struct device *pdevice;
 46 
 47 
 48 
 49     result = alloc_chrdev_region(&(gslDriverParameters.uiDeviceNumber), 0, 1, DEVICE_NAME);
 50 
 51     if(result < 0)
 52 
 53     {
 54 
 55         printk(KERN_ALERT DEVICE_NAME " alloc_chrdev_region error\n");
 56 
 57         return result;
 58 
 59     }
 60 
 61 
 62 
 63     gslDriverParameters.pslDriverClass = class_create(THIS_MODULE, DEVICE_NAME);
 64 
 65     if(IS_ERR(gslDriverParameters.pslDriverClass)) 
 66 
 67     {
 68 
 69         printk(KERN_ALERT DEVICE_NAME " class_create error\n");
 70 
 71 
 72 
 73         result = PTR_ERR(gslDriverParameters.pslDriverClass);
 74 
 75         goto CLASS_CREATE_ERROR;
 76 
 77     }
 78 
 79 
 80 
 81     cdev_init(&(gslDriverParameters.slCharDevice), &gslNvmDriverFileOperations);
 82 
 83     gslDriverParameters.slCharDevice.owner = THIS_MODULE;
 84 
 85 
 86 
 87     result = cdev_add(&(gslDriverParameters.slCharDevice), gslDriverParameters.uiDeviceNumber, 1);
 88 
 89     if(result < 0) 
 90 
 91     {
 92 
 93         printk(KERN_ALERT DEVICE_NAME " cdev_add error\n");
 94 
 95         goto CDEV_ADD_ERROR;
 96 
 97     }
 98 
 99 
100 
101     pdevice = device_create(gslDriverParameters.pslDriverClass, NULL, gslDriverParameters.uiDeviceNumber, NULL, DEVICE_NAME);
102 
103     if(IS_ERR(pdevice)) 
104 
105     {
106 
107         printk(KERN_ALERT DEVICE_NAME " device_create error\n");
108 
109 
110 
111         result = PTR_ERR(pdevice);
112 
113         goto DEVICE_CREATE_ERROR;
114 
115     }
116 
117 
118 
119     return 0;
120 
121 
122 
123 DEVICE_CREATE_ERROR:
124 
125     cdev_del(&(gslDriverParameters.slCharDevice));
126 
127 
128 
129 CDEV_ADD_ERROR:
130 
131     class_destroy(gslDriverParameters.pslDriverClass);
132 
133 
134 
135 CLASS_CREATE_ERROR:
136 
137     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);
138 
139 
140 
141     return result;
142 
143 }
144 
145 
146 
147 void UninitialCharDevice(void)
148 
149 {
150 
151     device_destroy(gslDriverParameters.pslDriverClass, gslDriverParameters.uiDeviceNumber);
152 
153 
154 
155     cdev_del(&(gslDriverParameters.slCharDevice));
156 
157 
158 
159     class_destroy(gslDriverParameters.pslDriverClass);
160 
161 
162 
163     unregister_chrdev_region(gslDriverParameters.uiDeviceNumber, 1);
164 
165 }
166 
167 
168 
169 static int DriverInitialize(void)
170 
171 {
172 
173     DEBUG_PRINT(DEVICE_NAME " Initialize\n");
174 
175 
176 
177     return InitalizeCharDevice();
178 
179 }
180 
181 
182 
183 static void DriverUninitialize(void)
184 
185 {
186 
187     DEBUG_PRINT(DEVICE_NAME " Uninitialize\n");
188 
189 
190 
191     UninitialCharDevice();
192 
193 }
194 
195 
196 
197 module_init(DriverInitialize);
198 
199 module_exit(DriverUninitialize);

7、DriverFileOperations.h

C++

代码语言:javascript
复制
 1 #ifndef DriverFileOperations_H
 2 
 3 #define DriverFileOperations_H
 4 
 5 int DriverOpen(struct inode *pslINode, struct file *pslFileStruct)
 6 
 7 int DriverClose(struct inode *pslINode, struct file *pslFileStruct);
 8 
 9 ssize_t DriverRead(struct file *pslFileStruct, char __user *pBuffer, size_t nCount, loff_t *pOffset);
10 
11 ssize_t DriverWrite(struct file *pslFileStruct, const char __user *pBuffer, size_t nCount, loff_t *pOffset);
12 
13 long DriverIOControl(struct file *pslFileStruct, unsigned int uiCmd, unsigned long ulArg);
14 
15 int DriverMMap(struct file *pslFileStruct, struct vm_area_struct *pslVirtualMemoryArea);
16 
17 #endif

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

Makefile

代码语言:javascript
复制
 1 ifneq ($(KERNELRELEASE),)
 2 
 3     obj-m := PrintModule.o
 4 
 5     PrintModule-objs := DriverMain.o DriverFileOperations.o
 6 
 7 EXTRA_CFLAGS := -DTEST_DEBUG -ggdb -O0
 8 
 9 else
10 
11     KERNELDIR ?= /lib/modules/$(shell uname -r)/build
12 
13     PWD := $(shell pwd)
14 
15 default:
16 
17     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
18 
19     rm *.order *.symvers *.mod.c *.o .*.o.cmd .*.cmd .tmp_versions -rf
20 
21 endif

9、运行测试

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

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

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

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、运行环境
  • 2、内核模块模型说明
    • (1)驱动和一般应用程序的执行方式很大不同
      • (2)回调方式:
      • 3、内核模型常见的回调函数举例
        •  (1)DriverInitialize
          • (2)DriverUninitialize
            • (3)DriverOpen
              • (4)DriverRead
                • (5)DriverWrite
                  • (7)DriverIOControl
                    • (8)DriverMMap
                    • 4、DriverMain.c
                    • 5、DriverMain.h
                    • 6、DriverFileOperations.c
                    • 7、DriverFileOperations.h
                    • 8、编译内核模块的MakeFile文件:
                    • 9、运行测试
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档