字符设备驱动基础1——简单的驱动源代码分析

以下内容源于朱有鹏嵌入式课程的学习,如有侵权请告知删除。

参考博客:linux驱动开发(一) - biaohc - 博客园

一、驱动源代码示例

/********module_test.c代码*********/#include <linux/module.h>	// module_init  module_exit
#include <linux/init.h>		// __init   __exit
#include <linux/fs.h>//这里手动定义主设备号,之前必须确认200没有被使用,查看方法:cat /proc/devices。
//比较好的方法是内核自动分配。
#define MYMAJOR	 200
#define MYNAME		"testchar"static int test_chrdev_open(struct inode *inode, struct file *file)
{// 这个函数中真正应该放置的是打开这个设备的硬件操作代码部分// 但是现在暂时我们写不了这么多,所以用一个printk打印个信息来做代表。printk(KERN_INFO "test_chrdev_open\n");return 0;
}static int test_chrdev_release(struct inode *inode, struct file *file)
{printk(KERN_INFO "test_chrdev_release\n");return 0;
}// 自定义一个file_operations结构体变量,并且去填充.
//这里的.只是结构体变量初始化的一种方法而已。
//file_operations是内核中已经定义好的结构体。
static const struct file_operations test_fops = {.owner		= THIS_MODULE,		// 惯例,直接写即可.open		= test_chrdev_open,	// 将来应用open打开这个设备时// 实际调用的就是这个.open对应的函数.release	= test_chrdev_release,		
};// 模块安装函数
static int __init chrdev_init(void)
{	int ret = -1;printk(KERN_INFO "chrdev_init helloworld init\n");// 在module_init宏调用的函数中去注册字符设备驱动ret = register_chrdev(MYMAJOR, MYNAME, &test_fops);if (ret){printk(KERN_ERR "register_chrdev fail\n");return -EINVAL;}printk(KERN_INFO "register_chrdev success...\n");return 0;
}// 模块卸载函数
static void __exit chrdev_exit(void)
{printk(KERN_INFO "chrdev_exit helloworld exit\n");// 在module_exit宏调用的函数中去注销字符设备驱动unregister_chrdev(MYMAJOR, MYNAME);}module_init(chrdev_init);
module_exit(chrdev_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");				// 描述模块的许可证
MODULE_AUTHOR("aston");				// 描述模块的作者
MODULE_DESCRIPTION("module test");	// 描述模块的介绍信息
MODULE_ALIAS("alias xxx");			// 描述模块的别名信息

二、解释说明

1、常用的模块操作命令

lsmod命令(list module,将模块列表显示)

功能是打印出当前内核中已经安装的模块列表。

insmod命令(install module,安装模块)

功能是向当前内核中安装一个模块,用法是insmod xxx.ko

modinfo(module information,模块信息)

功能是打印出一个内核模块的自带信息,用法是modinfo xxx.ko。

rmmod(remove module,卸载模块)

功能是从当前内核中卸载一个已经安装的模块,用法是rmmod xxx(不加.ko后缀)。

2、模块的安装与卸载

(1)模块的安装:insmod与module_init宏

执行insmod命令时,insmod内部实际执行的是使用module_init宏所声明的函数。

比如insmod module_test.ko时,insmod命令内部实际执行的操作是调用chrdev_init函数

(2)模块的卸载:rmmod和module_exit宏

和上面阐述的是同一个道理,可以使用lsmod命令查看rmmod前后系统的模块记录变化。

3、模块的版本信息

(1)使用modinfo命令查看模块的版本信息

root@ubuntu:/home/xjh/iot/embedded_basic/rootfs/tmp# modinfo module_test.ko 
filename:       /home/xjh/iot/embedded_basic/rootfs/tmp/module_test.ko
alias:          alias xxx
description:    module test
author:         aston
license:        GPL
depends:  //这是依赖,比如usb-wifi的驱动依赖usb的驱动      
vermagic:       2.6.35.7 preempt mod_unload ARMv7  //这是版本号
root@ubuntu:/home/xjh/iot/embedded_basic/rootfs/tmp#

(2)驱动的版本信息与内核的版本信息要一致

使用insmod命令安装驱动模块时,驱动模块的版本信息要与内核版本信息一致。这是一种安全措施,目的是为了保证模块和内核的兼容性。如果不一致,将报错:

insmod: ERROR: could not insert module module_test.ko: Invalid module format;

如何保持一致?确保某个内核源码树,既用来生成用来烧录的内核镜像,也用来编译驱动模块。

4、模块中常用宏

MODULE_xxx,这些宏用来添加驱动模块描述信息。

(1)MODULE_LICENSE,模块的许可证。

一般声明为GPL许可证,缺少可能会出现莫名其妙的错误(一些明显存在的函数提升找不到)。

(2)MODULE_AUTHOR,编写作者。

(3)MODULE_DESCRIPTION,模块描述。

(4)MODULE_ALIAS,别名信息。

5、函数修饰符__init、__exit

(1)函数修饰符__init

1)本质

__init 本质上是宏定义,在内核源代码中有#define __init xxxx。

作用

它的作用,是将所修饰的函数放入.init.text段(默认情况下函数被放入.text段中)。

使用这个修饰符有什么好处呢?

被__init 所修饰的函数,都被链接器链接放入.init.text段中。内核启动时会统一加载.init.text段中的这些模块安装函数,加载完后就会把这个段给释放掉以节省内存(因为安装完后这些函数就没用了)。

补充说明

下划线越多,越深入内核深处。

(2)函数修饰符__exit

和__init类似的意义,不赘述。

6、printk函数详解

(1)printk函数作用

在内核源码中用来打印信息的函数。

(2)printk和printf的差别

printf是C库函数,在应用层编程中使用,不能在linux内核源代码中使用;

printk是内核源码中的一个普通函数,只能在内核源码范围内使用,不能在应用编程中使用。

(3)printk可以设置打印级别

1)打印级别的意义

应用程序中的调试信息要么全部打开要么全部关闭,一般用条件编译(DEBUG宏)来实现;但是内核非常庞大,打印信息非常多,因此需要设置打印级别。printk的打印级别,可以用来控制printk打印的这条信息是否在终端上显示的。

2)打印级别

3)查看打印级别

可以使用“cat /proc/sys/kernel/printk”查看打印级别。

4)设置打印级别

可以用“echo 4 /proc/sys/kernel/printk”设置打印级别为4。 

5)命令行设置打印信息级别

在命令行中也可以设置打印信息级别,级别值为0-7。在执行printk的时候,对比printk中的打印级别与命令行中设置的打印级别,发现printk小于命令行设置级别的信息会被放行打印出来,大于的就被拦截。但ubuntu中不管如何设置级别,都不能直接打印出来,必须使用dmesg命令去查看。

7、关于驱动模块中的头文件

驱动源代码中包含的头文件,和应用程序中包含的头文件不同。

应用程序所包含的头文件,是应用层的头文件,一般是编译器带来的,与操作系统无关。比如 gcc 的头文件路径在 /usr/include下。

驱动源码所包含的头文件,是内核源代码include目录下的头文件,属于内核源码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/461299.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 数据检查_mysql数据一致性检查及修复

percona-toolkit-2.2.20-1.noarchmysql 5.6.29-logmaster:192.168.166.129slave:192.168.166.131一、创建数据库校验存放库CREATE DATABASE IF NOT EXISTS percona CHARACTER SET utf8;二、建立数据校验用户GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO checksu…

字符设备驱动基础3——使用register_chrdev()函数注册字符设备

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、系统工作原理 1、工作流程 系统的整体工作流程是&#xff1a;应用层—>API—>设备驱动—>硬件。 操作系统提供的API包括open、read、write、close等函数&#xff0c;它们只是一种操作逻…

win7在未关闭vmware情况下直接关机,导致虚拟机无法克隆

今天有点小激动啊&#xff0c;着急关机&#xff0c;结果发现重启之后的虚拟机不能进行克隆操作。系统提示如下&#xff1a;the Specific Virtual Disk Needs Repair .查询“度娘”&#xff0c;突然看到一篇文章说&#xff0c;删除这啊&#xff0c;修改那的....特别复杂&#xf…

hdu 1159(最长公共子序列)

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1159 思路&#xff1a;dp[i][j]表示s1从0~i-1,s2从0~j-1的最长公共子序列&#xff1b; 递推方程为&#xff1a;dp[i][j](s1[i-1]s2[j-1])?d[i-1][j-1]1:max(dp[i-1][j],dp[i][j-1]); View Code 1 #include<…

mysql applier_MySQL推出Applier,可实时复制数据到Hadoop-阿里云开发者社区

http://labs.mysql.comMySQL复制操作可以将数据从一个MySQL服务器(主)复制到其他的一个或多个MySQL服务器(从)。试想一下&#xff0c;如果从服务器不再局限为一个MySQL服务器&#xff0c;而是其他任何数据库服务器或平台&#xff0c;并且复制事件要求实时进行&#xff0c;是否可…

字符设备驱动基础4——读写接口的操作实践

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、细节提要 1、与用户与内核数据交换有关的函数 &#xff08;1&#xff09;copy_from_user()函数 该将数据从用户空间复制到内核空间。 如果成功复制则返回0&#xff0c;如果不成功复制则返回尚未…

从 Google Code 迁移代码到 GitHub 上

从Google Code迁移代码到github上的步骤: 首先访问 https://github.com/nirvdrum/svn2git 安装svn2git工具。创建一个空白目录&#xff0c;进入该目录执行 svn2git http://xxxxx.googlecode.com/svn , 注意&#xff0c;以svn结尾&#xff0c;不要加/trunk导出完毕后&#xff0c…

LAMP架构,纯文本作品

&#xff08;一&#xff09;Apache服务的编译安装1. 查找软件包位置[rootlocalhost ~]#cd /soft/LNS/chapter05[rootlocalhost ~]#ls2.解压包到指定位置[rootlocalhost ~]#tar zxf httpd-2.2.17.tar.gz -C /usr/src/3.编译安装Apache[rootlocalhost ~]#cd /usr/src/httpd-2.2.1…

ef sqlserver切换到mysql_可以为MySql和SqlServer使用EF上下文吗?

我有两个实体框架上下文,一个用于MySql,一个用于sql.如果我运行该应用程序,则会出现以下错误The default DbConfiguration instance was used by the Entity Framework before the MySqlEFConfiguration type was discovered.但是,如果我确实通过给应用程序指定Database.SetIni…

字符设备驱动高级篇1——注册字符设备驱动的新接口

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、注册字符设备驱动的老接口 在《字符设备驱动基础》里&#xff0c;注册字符设备驱动使用的函数是register_chrdev()函数。 该函数的介绍&#xff0c;见博客字符设备驱动基础3——使用register_ch…

ural 1129 (求数据)

先记下来。在test 7wa了。如果谁有数据希望可以指点下。thx. 1 // File Name: 1129.cpp2 // Author: Missa3 // Created Time: 2013/3/12 星期二 17:31:534 5 #include<iostream>6 #include<cstdio>7 #include<cstring>8 #include<algorithm>9 #includ…

码农提高工作效率

原文链接http://www.cnblogs.com/huang0925/p/3612741.html 俗话说&#xff0c;天下武功&#xff0c;唯快不破。也就是说要练成天下高手的话&#xff0c;出招速度一定要快&#xff0c;这样才能在江湖上立足&#xff0c;不至于掉了脑袋。而程序员要在IT界混出个名堂&#xff0c;…

mysql分区表mycat_MySQL 中间件之Mycat垂直分表配置

垂直分表就是将一个库下的多个表拆分到多个MySQL实例&#xff0c;实现库压力分流。通过GTID模式复制&#xff0c;db01与db02之间不进行任何连接与复制当前环境&#xff1a;mycat --> db01与db02db01 --> db03db02 --> db04当前垂直分表架构&#xff1a;后端数据库创建…

Oracle Stream配置详细步骤

Oracle Stream配置详细步骤 作者: 杨宝秋,  出处:IT168 1 引言 Oracle Stream功能是为提高数据库的高可用性而设计的&#xff0c;在Oracle 9i及之前的版本这个功能被称为Advance Replication。Oracle Stream利用高级队列技术&#xff0c;通过解析归档日志&#xff0c;将归档日…

字符设备驱动高级篇2——注册字符设备驱动的函数代码分析

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、旧接口register_chrdev()函数 上文说到&#xff0c;旧接口register_chrdev()函数内部同时完成了设备号的分配与驱动的注册&#xff0c;现在我们来分析是否真的如此。 1、函数的调用层次关系 …

LR学习视频

0 性能测试常见用语http://www.boobooke.com/v/bbk15771 lr目录分析http://www.boobooke.com/v/bbk15742.1 lr界面分析http://www.boobooke.com/v/bbk17352.2 lr界面分析http://www.boobooke.com/v/bbk17362.3 lr界面分析http://www.boobooke.com/v/bbk17373 lr常用术语http://…

深入浅出mysql gtid_深入理解MySQL GTID

GTID的概念何为GITDGTID(global transaction identifier)是全局事务标识符&#xff0c;在MySQL5.6版本中作为一个超级特性被推出。事务标识不仅对于Master(起源)的服务器来说是惟一的&#xff0c;而且在整个复制拓扑架构来说&#xff0c;也是全局唯一的。1.GTID的格式GTID sou…

winform 64位系统中使用

WINFOR编译成X86的 转载于:https://blog.51cto.com/agilitygod/1419939

字符设备驱动高级篇3——自动创建设备文件

以下内容源于朱有鹏嵌入式课程学习与整理&#xff0c;如有侵权请告知删除。 问题引入 之前在应用层测试驱动源程序时&#xff0c;需要先安装驱动模块&#xff0c;安装驱动模块后会得到一个主设备号&#xff0c;然后在命令行利用mknod命令“mknod /dev/xxx c 主设备号 次设备号”…

long 转为string_面试必问 Redis数据结构底层原理String、List篇

点击关注上方“Java大厂面试官”&#xff0c;第一时间送达技术干货。阅读文本大概需要 8 分钟。前言今天来整理学习下Redis有哪些常用数据结构&#xff0c;都是怎么使用的呢&#xff1f;首先看下全局存储结构。全局存储结构基础你们肯定都知道&#xff0c;redis支持的基础数据结…