浅谈linux - 驱动框架

概述

linux设备驱动服务于应用程序,是链接硬件设备和应用程序之间的桥梁。主要做两部分工作:

1、操作硬件。

2、给用户提供访问操作硬件的接口(函数)。

驱动程序

1、驱动入口函数通过module_init指定,函数类型为int func(void)。

/* 驱动加载时执行,调用insmod或者modprobe加载驱动 */
static int __init drv_base_init(void)
{
    printk("hello : drv_base_init\n");
    return 0;
}
module_init(drv_base_init);     /* 指定入口函数 */

2、驱动出口函数通过module_exit指定,函数类型为void func(void)。

/* 驱动卸载时执行,调用rmsmod或者modprobe -r卸载驱动 */
static void __exit drv_base_exit(void)
{
    printk("bye : drv_base_exit\n");
}
module_exit(drv_base_exit);     /* 指定出口函数 */

3、模块许可证通过MODULE_LICENSE声明。

MODULE_LICENSE("GPL");          /* 模块的许可证声明 */

4、模块的其它说明,包括作者、版本号、描述等,调用命令modinfo查看。

/* 调用modinfo xx(模块名)查看 */
MODULE_AUTHOR("feng");          /* 模块的作者 */
MODULE_VERSION ("1.00");        /* 模块版本号 */
/* MODULE_DESCRIPTION("xxxxx");    模块描述 */
/* MODULE_ALIAS("xxx");            模块别名 */

Makefile

1、指定路径,包括根文件、驱动存放位置、内核路径等。

#根文件所在目录
ROOTFS_DIR = /home/feng/atomic/rootfs

#驱动目录路径
DRV_DIR = $(ROOTFS_DIR)/home/drv
DRV_DIR_LIB = $(ROOTFS_DIR)/lib/modules/4.1.15

#内核路径
KERNEL_DIR =/home/feng/atomic/resource/linux-imx-rel_imx_4.1.15_2.1.0_ga

#当前文件路径
CURR_DIR = $(shell pwd)

2、指定编译器。

#交叉编译工具链
CROSS_COMPILE = arm-linux-gnueabihf-
CC = $(CROSS_COMPILE)gcc

3、编译模块,注意install命令用于将模块拷贝到目标机指定位置。

#KERNELRELEASE由内核makefile赋值
ifeq ($(KERNELRELEASE), )

all:
    #编译模块
    make -C $(KERNEL_DIR) M=$(CURR_DIR) modules

clean:
    #清除模块文件
    make -C $(KERNEL_DIR) M=$(CURR_DIR) clean

install:
    #拷贝模块文件
    cp -raf *.ko $(DRV_DIR_LIB)

else
#指定编译什么文件
obj-m += drv_base.o

endif

示例

★包含源文件drv_base.c和makefile文件Makefile(均已验证通过)。

 drv_base.c

/**
 * @Filename : drv_base.c
 * @Revision : $Revision: 1.00 $
 * @Author : Feng(更多编程相关的知识和源码见微信公众号:不只会拍照的程序猿,欢迎订阅)
 * @Description : 驱动框架示例
**/

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

/* 驱动加载时执行,调用insmod或者modprobe加载驱动 */
static int __init drv_base_init(void)
{
    printk("hello : drv_base_init\n");
    return 0;
}

/* 驱动卸载时执行,调用rmsmod或者modprobe -r卸载驱动 */
static void __exit drv_base_exit(void)
{
    printk("bye : drv_base_exit\n");
}

module_init(drv_base_init);     /* 指定入口函数 */
module_exit(drv_base_exit);     /* 指定出口函数 */

/* 调用modinfo xx(模块名)查看 */
MODULE_LICENSE("GPL");          /* 模块的许可证声明 */
MODULE_AUTHOR("feng");          /* 模块的作者 */
MODULE_VERSION ("1.00");        /* 模块版本号 */
/* MODULE_DESCRIPTION("xxxxx");    模块描述 */
/* MODULE_ALIAS("xxx");            模块别名 */

 Makefile

#根文件所在目录
ROOTFS_DIR = /home/feng/atomic/rootfs

#交叉编译工具链
CROSS_COMPILE = arm-linux-gnueabihf-
CC = $(CROSS_COMPILE)gcc

#驱动目录路径
DRV_DIR = $(ROOTFS_DIR)/home/drv
DRV_DIR_LIB = $(ROOTFS_DIR)/lib/modules/4.1.15

#KERNELRELEASE由内核makefile赋值
ifeq ($(KERNELRELEASE), )

#内核路径
KERNEL_DIR =/home/feng/atomic/resource/linux-imx-rel_imx_4.1.15_2.1.0_ga

#当前文件路径
CURR_DIR = $(shell pwd)

all:
    #编译模块
    make -C $(KERNEL_DIR) M=$(CURR_DIR) modules

clean:
    #清除模块文件
    make -C $(KERNEL_DIR) M=$(CURR_DIR) clean

install:
    #拷贝模块文件
    cp -raf *.ko $(DRV_DIR_LIB)

else
#指定编译什么文件
obj-m += drv_base.o

endif

结论

1、进入目录,执行make命令,编译模块。

feng:drv_base$ make
#编译模块
make -C /home/feng/atomic/resource/linux-imx-rel_imx_4.1.15_2.1.0_ga M=/mnt/hgfs/Share/linux/atomic/driver/drv_base modules
make[1]: 进入目录“/home/feng/atomic/resource/linux-imx-rel_imx_4.1.15_2.1.0_ga”
  CC [M]  /mnt/hgfs/Share/linux/atomic/driver/drv_base/drv_base.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /mnt/hgfs/Share/linux/atomic/driver/drv_base/drv_base.mod.o
  LD [M]  /mnt/hgfs/Share/linux/atomic/driver/drv_base/drv_base.ko
make[1]: 离开目录“/home/feng/atomic/resource/linux-imx-rel_imx_4.1.15_2.1.0_ga”
feng:drv_base$ 

2、执行make install命令,拷贝模块到目标机指定位置。

feng:drv_base$ make install 
#拷贝模块文件
cp -raf *.ko /home/feng/atomic/rootfs/lib/modules/4.1.15
feng:drv_base$  

3、装载/卸载模块,在目标机上执行insmod/rmmod命令。

/lib/modules/4.1.15 # insmod drv_base.ko 
hello : drv_base_init
/lib/modules/4.1.15 # lsmod 
Module                  Size  Used by    Tainted: G  
drv_base                 678  0 
/lib/modules/4.1.15 # rmmod drv_base
bye : drv_base_exit
/lib/modules/4.1.15 #  

4、也可使用modprobe/modprobe -r装载和卸载模块,注意,在使用之前需要先执行depmod命令,用以分析加载模块的依赖性,并生成modulse.dep文件和映射文件,在多模块的情况下尤其有用。

/lib/modules/4.1.15 # depmod
/lib/modules/4.1.15 # ls
drv_base.ko      modules.alias    modules.dep      modules.symbols
/lib/modules/4.1.15 # modprobe drv_base.ko 
/lib/modules/4.1.15 # lsmod
Module                  Size  Used by    Tainted: G  
drv_base                 678  0 
/lib/modules/4.1.15 # modprobe -r drv_base
bye : drv_base_exit
/lib/modules/4.1.15 #  

5、查看作者、版本信息,使用modinfo命令。

/lib/modules/4.1.15 # modinfo drv_base
filename:       drv_base.ko
author:         feng
license:        GPL
version:        1.00
srcversion:     8C72DB448C1E6781B7DB1A4
depends:        
vermagic:       4.1.15 SMP preempt mod_unload modversions ARMv6 p2v8 
/lib/modules/4.1.15 # 

6、综上,在装载模块的时候,程序执行drv_base_init函数,输出hello : drv_base_init,卸载模块时候,程序执行drv_base_exit函数,输出:bye : drv_base_exit,同时执行modinfo查看到作者、版本号与代码中设置一致。

往期 · 推荐

帮你自动化办公的python-自动提取pdf指定页(文件处理篇)

帮你自动化办公的python-自动提取pdf指定页(项目概述)

也没想象中那么神秘的数据结构-一种通用化的双向链表设计(底层源码)

也没想象中那么神秘的数据结构-一环扣一环的“链表”(双向链表)

我用C语言玩对象,偷偷关注着你的观察者模式(基类设计)

关注

更多精彩内容,请关注微信公众号:不只会拍照的程序猿,本人致力分享linux、设计模式、C语言、嵌入式、编程相关知识,也会抽空分享些摄影相关内容,同样也分享大量摄影、编程相关视频和源码,另外你若想要本文章源码请关注公众号:不只会拍照的程序猿,后台回复:linux驱动源码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不只会拍照的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值