Linux驱动模块加载和卸载以及设备注册与注销
一、驱动模块的加载和卸载
Linux驱动有两种运行方式,第一种就是将驱动编译进Linux内核中,这样当Linux内核启动的时候就会自动运行驱动程序。第二种就是将驱动编译成模块(Linux下模块扩展名为.ko),在Linux内核启动以后使用“insmod”命令加载驱动模块。在调试驱动的时候一般都选择将其编译为模块,这样修改驱动以后只需要编译一下驱动代码即可,不需要编译整个Linux代码。而且在调试的时候只需要加载或者卸载驱动模块即可,不需要重启整个系统。总之,将驱动编译为模块最大的好处就是方便开发,当驱动开发完成,确定没有问题以后就可以将驱动编译进Linux内核中,当然也可以不编译进Linux内核中,具体看自己的需求。模块有加载和卸载两种操作,在编写驱动的时候需要注册这两种操作函数,模块的加载和卸载注册函数如下:
module_init(xxx_init);
//注册模块加载函数
module_exit(xxx_exit);
//注册模块卸载函数
module_init函数用来向Linux内核注册一个模块加载函数,参数xxx_init就是需要注册的具体函数,当使用“insmod”命令加载驱动的时候,xxx_init这个函数就会被调用。module_exit()函数用来向Linux内核注册一个模块卸载函数,参数xxx_exit就是需要注册的具体函数,当使用“rmmod”命令卸载具体驱动的时候xxx_exit函数就会被调用。字符设备驱动模块加载和卸载模板如下所示:
/*驱动入口函数*/
static int _init xxx_init(void)
{/*入口函数具体内容*/
return 0;
}
/*驱动出口函数*/
static void _ exit xxx _ exit ( void )
{/*出口函数具体内容*/
}/*将上面两个函数指定为驱动的入口和出口函数*/
module_init(xxx_init);
module_exit(xxx_exit);
- 第2行,定义了个名为xxx_init的驱动入口函数,并且使用了“_init”来修饰。
- 第9行,定义了个名为xxx_exit的驱动出口函数,并且使用了“_exit”来修饰。
- 第15行,调用函数module_init来声明xxx_init为驱动入口函数,当加载驱动的时候xxx_init函数就会被调用。
- 第16行,调用函数module_exit来声明xxx_exit为驱动出口函数,当卸载驱动的时候xxx_exit函数就会被调用。
二、insmod和rmmod命令
1、insmod命令
驱动编译完成以后扩展名为.ko,有两种命令可以加载驱动模块:insmod和modprobe,insmod是最简单的模块加载命令,此命令用于加载指定的.ko模块,比如加载drv.ko这个驱动模块,命令如下:
insmod drv.ko
insmod命令不能解决模块的依赖关系,比如drv.ko依赖first.ko这个模块,就必须先使用insmod命令加载first.ko这个模块,然后再加载drv.ko这个模块。但是modprobe就不会存在这个问题,modprobe会分析模块的依赖关系,然后会将所有的依赖模块都加载到内核中,因此modprobe命令相比insmod要智能一些。modprobe命令主要智能在提供了模块的依赖性分析、错误检查、错误报告等功能,推荐使用modprobe命令来加载驱动。modprobe命令默认会去/lib/modules/目录中查找模块
因此modprobe命令默认会到/lib/modules/4.1.15这个目录中查找相应的驱动模块,一般自己制作的根文件系统中是不会有这个目录的,所以需要自己手动创建。
2、rmmod命令
驱动模块的卸载使用命令“rmmod”即可,比如要卸载drv.ko,使用如下命令即可:
rmmod drv.ko
也可以使用“modprobe -r”命令卸载驱动,比如要卸载drv.ko,命令如下:
modprobr -r drv.ko
使用modprobe命令可以卸载掉驱动模块所依赖的其他模块,前提是这些依赖模块已经没有被其他模块所使用,否则就不能使用modprobe来卸载驱动模块。所以对于模块的卸载,还是推荐使用rmmod命令。
三、字符设备注册和注销
对于字符设备驱动而言,当驱动模块加载成功以后需要注册字符设备,同样,卸载驱动模块的时候也需要注销掉字符设备。字符设备的注册和注销函数原型如下所示:
static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations*fops)
static inline void unregister_chrdev(unsigned int major, const char *name)
1、register_chrdev函数用于注册字符设备,此函数一共有三个参数,这三个参数的含义如下:
- major:主设备号,Linux下每个设备都有一个设备号,设备号分为主设备号和次设备号两部分。
- name:设备名字,指向一串字符串。
- fops:结构体file_operations类型指针,指向设备的操作函数集合变量。
2、unregister_chrdev函数用户注销字符设备,此函数有两个参数,这两个参数含义如下:
- major:要注销的设备对应的主设备号。
- name:要注销的设备对应的设备名。
一般字符设备的注册在驱动模块的入口函数xxx_init中进行,字符设备的注销在驱动模块的出口函数xxx_exit中进行。在示例代码40.2.2.1中字符设备的注册和注销,内容如下所示:
static struct file_operations test_fops;
/*驱动入口函数*/
static int _init xxx_init(void)
{/*入口函数具体内容*/int retvalue = 0;/*注册字符设备驱动*/retvalue = register_chrdev(200,"chrtest", &test_fops);if(retvalue<0){/*字符设备注册失败,自行处理*/}return 0;
}
/*驱动出口函数*/
static void_exit xxx_exit(void)
{/*注销字符设备驱动*/unregister_chrdev(200,"chrtest");
}
/*将上面两个函数指定为驱动的入口和出口函数*/
module_init(xxx_init);
module_exit(xxx_exit);
- 定义了一个file_operations结构体变量test_fops,test_fops就是设备的操作函数集合,只是此时我们还没有初始化test_fops中的open、release等这些成员变量,所以这个操作函数集合还是空的。
- 调用函数register_chrdev注册字符设备,主设备号为200,设备名字为“chrtest”,设备操作函数集合就是第1行定义的test_fops。要注意的一点就是,选择没有被使用的主设备号,输入命令“cat/proc/devices”可以查看当前已经被使用掉的设备号。
- 调用函数unregister_chrdev注销主设备号为200的这个设备。
以上即为Linux驱动模块加载和卸载的介绍!!!
Linux驱动模块加载和卸载以及设备注册与注销相关推荐
- Linux如何加载与卸载U盘
Linux如何加载与卸载U盘 第一:以root用户登陆 先加载USB模块 modprobe usb-storage 用fdisk -l 看看U盘的设备 假如U盘是sda1 第二:确定在 目录 ...
- Linux驱动3:驱动模块加载与卸载
目录 一.环境配置 1.开发板环境 2.uboot环境 ①设置bootargs ②设置bootcmd 二.加载驱动与卸载驱动 1.加载命令选择 2.创建目录环境以及驱动文件复制 3.加载驱动 提示①& ...
- linux驱动模块加载错误(insmod: can‘t insert ‘xxx.ko‘: invalid module format)的原因之一:内核或者配置不一致
问题现象:insmod方式加载某个驱动ko模块,提示insmod: can't insert 'xxx.ko': invalid module format 问题原因之一(也可能是概率较大的一个原因) ...
- linux驱动加载流程分析
linux驱动加载流程分析 内核是如何加载驱动的,有些是编译到内核里面,有些事编译成ko,让系统自动加载.总的说来,在Linux下可以通过两种方式加载驱动程序:静态加载和动态加载. 静态加载就是把驱动 ...
- Linux可加载内核模块(LKM)(转载)
转载: 漏天剑 文章导航: 为校长杯流尽最后一滴血, Lkm注射, 返回首页 Linux可加载内核模块(LKM) Linux可加载内核模块完全版 --黑客.病毒程序编写者和系统管理员的概念性指南 作者 ...
- 备份linux分区到usb,将Linux引导加载程序备份到USB的方法
本文介绍如何将Linux引导加载程序备份到USB以应对紧急情况.大多数Linux操作系统使用的引导加载程序称为Grub,这是一个简单的工具,可以配置为在PC启动时从菜单启动Linux发行版以及其他操作 ...
- 正确使用AssetBundle加载和卸载
在使用Unity开发项目时,AssetBundle是必须使用的,对资源进行打包加载,因为移动端游戏包体的大小对用户体验非常重要,对内存的使用更加重要,下面我们就介绍一下关于AssetBundlle的使 ...
- 基于PsSetLoadImageNotifyRoutine实现监控模块加载并卸载已加载模块(卸载DLL、EXE和sys等加载)
背景 对于内核层实现监控模块的加载,包括加载DLL模块.内核模块等.你也许会想到 HOOK 各种内核函数来实现.确定,在内核层中的 HOOK 已经给人留下太多深刻的印象了,有 SSDT HOOK.In ...
- 生成PL设备树及动态加载PL程序和设备树
实验说明 操作环境: Windows 7/10 64bit Xilinx Vivado 2017.4 Ubuntu 14.04 表 1 开发板型号 是否支持本实验 TLZ7x-EasyEVM 支持 T ...
最新文章
- 喧哗的背后:Serverless 的概念及挑战
- SAP系统与MES系统的数据协同技术方案
- wps重复上一步快捷键_WPS表格怎么快速输入重复内容?快速输入重复内容的详细步骤...
- Java enum枚举
- 计算机专业英语的理解,计算机专业英语之理解网络地址
- android自动生成cardview,学习使用Material Design控件(三)使用CardView实现卡片效果...
- 工作3年,可视化毫无进步?小白都能看懂的干货,我真不想告诉你
- 字体设计灵感合集|字体决定了设计
- jQuery做个TextBox自动完成条
- mysql 使用内置函数来进行模糊搜索(locate()等)
- GB35114—③、证书和密钥要求、基本功能要求及性能要求
- 伍德里奇计量经济学第六章计算机答案,伍德里奇计量经济学导论计算机习题第六章第13题c_6.13...
- 用Java弹个Freepiano钢琴《The truth that you leave》
- 直播APP源码在ftp服务器搭建教程
- J2EE框架(StrutsHibernateSpring)的理解
- 学英语尽量不要从背词汇表开始
- Unity 透视相机世界和屏幕坐标系转换
- 【2022 年第十二届 MathorCup杯数学建模】D 题 移动通信网络站址规划和区域聚类问题 赛后总结、论文及代码
- 逻辑电路是计算机学的吗,逻辑电路可以使计算机具备什么能力 计算机具有逻辑判断能力,主要取决于( )。...
- 用户画像是怎么生成出来的