Linux驱动简单入门——学习笔记(1)

PC操作系统:Ubuntu 16.04 LTS
编译器:arm-poky-linux-gnueabi-gcc 4.9.1

基于i.mx6平台对Linux驱动模块修修改改也有段时间了,其中断断续续查了一大堆资料感觉知识并不那么连贯,是时候自己从基础开始整理整理了。


一、创建一个最小驱动模块模板

创建一个hello.c文件

#include<linux/init.h>
#include<linux/module.h>

/*************************************************************************************************/
//                           局部宏定义
/*************************************************************************************************/
#define EN_DEBUG                    1                                          /* 调试信息开关 */
#if EN_DEBUG
#define PRINT(x...)                 printk(KERN_EMERG x)                       /* 提高打印等级 */
#else
#define PRINT(x...)
#endif

/**************************************************************************************************
**  函数名称:  drv_init
**  功能:  驱动初始化函数,在加载时被调用
**  参数:  无
**  返回:  无
**************************************************************************************************/
static int __init drv_init(void)
{
    PRINT("%s ------ \n", __FUNCTION__);
    return 0;
}

/**************************************************************************************************
**  函数名称:  drv_exit
**  功能描述:  i2c驱动退出函数,在卸载时被调用
**  参数:  无
**  返回:  无
**************************************************************************************************/
static void __exit drv_exit(void)
{
    PRINT("%s ------ \n", __FUNCTION__);
}

module_init(drv_init);                                                         /* 模块初始化 */
module_exit(drv_exit);                                                         /* 模块卸载 */

MODULE_AUTHOR("hrx");                                                          /* 模块作者 */
MODULE_DESCRIPTION("Linux Driver");                                            /* 模块描述 */
MODULE_VERSION("1.0.0");                                                       /* 模块版本 */
MODULE_LICENSE("GPL");                                                         /* 模块遵守的License */

该模块实现的功能

  • 加载函数
  • 卸载函数
  • 作者、描述、版本、许可权限等描述
  • 打印调试信息(printk)

打印调试解释

  • 用户层使用printf函数
  • Linux内核层使用prink函数
  • prink中的KERN_EMERG宏是设定输出级别(我选的这个是可以直接输出调试信息的输出级别),更多定义在kernel\include\linux\kern_levels.h文件中可以看到。
  • 如果打印级别不高无法输出的话也可以通过dmesg -c命令输出缓存的打印信息(-c是为了输出后清空缓存)。

二、编写Makefile

#当前目录路径
PWD = $(shell pwd)

#Linux内核根目录路径
KERNEL_DIR = $(PWD)/../../kernel

#驱动名称
DRVNAME = hello

#obj-m选项是会以模块进行编译,不会被编译进内核,而是独立生成一个.ko文件
#obj-y选项是会被编译进内核
obj-m += hello.o

build:
	$(MAKE) -C $(KERNEL_DIR) M=$(PWD)

clean:
	@rm -rf *.o *.ko .*.cmd *.mod.c *.order *.symvers .tmp_versions *~

说明

  • KERNEL_DIR为相对于当前Makefile的内核目录路径。
  • **$(MAKE)**是make命令的宏定义,其中可能包含其他参数(我这里是只有make)。
  • -C这个C是大写的,是为了切换到KERNEL_DIR目录再进行make。
  • **M=**是指定Linux驱动源码所在的目录。

三、生成驱动文件(*.ko)

1、配置交叉编译环境

由于我是在开发板上用的,所以要交叉编译。
参考:配置imx6交叉编译环境

2、编译

执行make命令即可生成.ko文件。

make build

在这里插入图片描述

四、加载及卸载驱动

首先要先把hello.ko传到开发板上,才能执行后续操作。

1、加载驱动(insmod)

root@imx6qsabresd:/tmp# insmod hello.ko 
[ 7707.518557] drv_init ------ 

这就输出了初始化函数。

2、卸载驱动(rmmod)

root@imx6qsabresd:/tmp# rmmod hello.ko 
[ 7843.203066] drv_exit ------ 

这就输出了退出函数。

五、查看驱动信息

1、列出已加载的驱动模块(lsmod)

root@imx6qsabresd:/tmp# lsmod
    Tainted: G  
hello 832 0 - Live 0x7f057000 (O)

lsmod其实是读取了**/proc/modules**文件的内容

root@imx6qsabresd:/tmp# cat /proc/modules 
hello 832 0 - Live 0x7f057000 (O)

2、驱动加载信息储存位置

驱动被加载后会在 /sys/module/ 目录下生成一个与驱动文件同名的文件夹,里面存放着驱动加载信息。

root@imx6qsabresd:/tmp# ls -l /sys/module/hello/
-r--r--r--    1 root     root          4096 Nov 10 19:40 coresize
drwxr-xr-x    2 root     root             0 Nov 10 19:40 holders
-r--r--r--    1 root     root          4096 Nov 10 19:40 initsize
-r--r--r--    1 root     root          4096 Nov 10 19:40 initstate
drwxr-xr-x    2 root     root             0 Nov 10 19:40 notes
-r--r--r--    1 root     root          4096 Nov 10 19:40 refcnt
drwxr-xr-x    2 root     root             0 Nov 10 19:40 sections
-r--r--r--    1 root     root          4096 Nov 10 19:40 srcversion
-r--r--r--    1 root     root          4096 Nov 10 19:40 taint
--w-------    1 root     root          4096 Nov 10 19:35 uevent

3、查看驱动文件信息(modinfo)

  • 这个命令直接查询驱动文件,不需要加载。
  • 开发板被阉割了这个命令,这是在PC上查看的驱动文件信息。
  • 之前在驱动文件里定义的作者、描述、版本、许可权限等描述都可以查得到。
hrx@@@:~/Imx6/platform/driver/hello$ modinfo hello.ko
filename:       /home/hrx/Imx6/platform/driver/hello/hello.ko
license:        GPL
version:        1.0.0
description:    Linux Driver
author:         hrx
srcversion:     A5F2F4E32D4DF79D5CF15B7
depends:        
vermagic:       3.14.38-6UL_ga-svn12810 SMP preempt mod_unload modversions ARMv7 p2v8

参考1:https://blog.csdn.net/leon1741/article/details/78165507

发布了65 篇原创文章 · 获赞 107 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/lang523493505/article/details/104265663
今日推荐