要求:掌握添加设备驱动程序的方法
内容:
采用模块方法,添加一个新的设备驱动程序。
要求添加字符设备的驱动。
编写一个应用程序,测试添加的驱动程序。
<style type="text/css">
<!--
p
{margin-bottom:0.21cm}
-->
</style>
linxu系统中,在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:
-
对设备初始化和释放.
-
把数据从内核传送到硬件和从硬件读取数据.
-
读取应用程序传送给设备文件的数据和回送应用程序请求的数据.
-
检测和处理设备出现的错误.
设备分为两种:字符设备和块设备,这里就以简单的字符设备为例。
<style type="text/css">
<!--
p
{margin-bottom:0.21cm}
-->
</style>
在设备驱动程序中有一个非常重要的结构file_operations,该结构的每个域都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。
struct file_operations {
int(*seek) (struct inode * ,structfile *, off_t ,int);
int (*read) (struct inode * ,structfile *, char ,int);
int (*write) (struct inode * ,structfile *, off_t ,int);
……
}
<style type="text/css">
<!--
p
{margin-bottom:0.21cm}
-->
</style>
编写设备驱动程序的主要工作是编写子函数,并填充file_operations的各个域。
例如:
Structfile_operations my_fops={
.read=my_read,
.write=my_write,
.open=my_open,
.release=my_release
}
<style type="text/css">
<!--
p
{margin-bottom:0.21cm}
-->
</style>
然后再定义函数my_read,my_write,my_open,my_release相应的函数体。
例如:
staticssize_t my_open(struct inode *inode,struct file *file){
staticint counter=0;
if(Device_Open)
return-EBUSY;
Device_Open++;
/*写入设备的信息*/
sprintf(msg,"the device hasbeen called %d times\n",counter++);
msg_ptr=msg;
return0;
}
<style type="text/css">
<!--
p
{margin-bottom:0.21cm}
-->
</style>
同时对于可卸载的内核模块(LKM),至少还有两个基本的模块:
<style type="text/css">
<!--
p
{margin-bottom:0.21cm}
-->
</style>
my_init用于注册设备,获得设备的主设备号
调用register_chrdev(0,“sky_driver(设备名)”,&my_fops);
my_exit用于注销设备
调用unregister_chrdev(my_major,“sky_driver(设备名)”);
然后在程序尾再调用这两个函数
Module_init(my_init);
Module_exit(my_exit)
MODULE_LICENSE(“GPL”);
不过如果使用特殊函数名
init_module 和cleanup_module,
就不用在程序最后加上上面那三行代码了。
废话少说,以下是实验过程:
首先编写驱动程序。
,开始进行实验:
1.编译驱动程序。
在控制台下进入文件所在目录,输入命令make。如图:
看到了吗?提示错误。原来需要用超级用户权限。
没有错误提示,说明make成功,进入文件夹下可以看到多了一些.k,.ko之类的文件。这就是编译好的模块。
2. 装载模块。
同样,必须要是root下才能进行。装载前,我们可以先看看系统中的模块:lsmod
装载,输入命令: insmod devDrv.ko
完成后,再看看系统中的模块,发现多了一个模块“devDrv”,表示我们成功加载了!
可以用命令查看系统日志信息:dmesg
看到如下信息:
这正是在我们的驱动程序中注册函数输出的内容哦!
3.分配次设备号。
每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们.设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序.。
分配前,我们必须要知道主设备号(其实在上一步中我们从dmesg中已经看到主设备好为250): cat /proc/devices
可见到这一行:250 myDevice,是了,主设备号为250.
现在我们分配从设备号:mknod /dev/myDevice c 250 0
实际上就是在虚拟文件夹/dev/中加一个设备(在系统看来是文件)myDevice ,注意,这个是设备名,在测试文件中真是要利用这个设备名打开设备。最后的0表示从设备号。可以随便分配(只要不冲突)。
此后便可以在/dev/目录下看到新建的设备myDevice了:ls /dev/
一切成功的话,就可以测试我们的驱动程序啦!
4.测试驱动程序。
首先要编译测试程序:gcc drvTest.c -o sb
得到sb可执行程序,再执行 :./sb
测试程序首先列出所有的设备名,让我们选中一个,当然输入myDevice啦:
<style type="text/css">
<!--
p
{margin-bottom:0.21cm}
-->
</style>正确读出之前存放在设备中的字符串!然后提示让我们输入一个字符串,随便啦:
最后是不是正确保存、读出了呢?of course !而且还告诉我们调用了几次这个设备呢!
5.删除设备、模块。
首先删除设备。就像删除普通文件一样:rm /dev/myDevice
删除后,看看/dev/目录下是佛已经木有myDevice 啦?:ls /dev/
接着删除模块:rmmod devDrv.
看看模块列表中是否已经没有devDrv模块了?:lsmod
在本次实验中,还特别添加了一些代码来给设备上锁,实现互斥,以免同时有多个进程读取设备造成混乱。(一般来说,字符设备如打印机是不能共享滴。。)观察驱动程序devDrv.c中两个函数
static int my_open(struct inode *inode, struct file *file)
{
if(mutex)
return -EBUSY;
mutex = 1;//上锁
printk("<1>main device : %d\n", MAJOR(inode->i_rdev));
printk("<1>slave device : %d\n", MINOR(inode->i_rdev));
printk("<1>%d times to call the device\n", ++counter);
try_module_get(THIS_MODULE);
return 0;
}
/* 每次使用完后会release */
static int my_release(struct inode *inode, struct file *file)
{
printk("Device released!\n");
module_put(THIS_MODULE);
mutex = 0;//开锁
return 0;
}
int 型mutex就是用来上锁的,它被初始化为0,一旦使用该设备,就首先要调用my_open函数,将mutex设置为1,如果此后还想使用该设备,必然因为mutex为1而返回-EBUSY,而终止。使用完该设备后,调用my_release释放设备,将mutex重新设回0.
特别注意,还有一个counter变量,使用来计量使用次数的。
makefile的格式相当严格,比如不能用8个空格来代替一个table键等。
makefile最后有一句:
devDrv一定要对应我们要编译的驱动程序devDrv.c的文件名。
源代码附上。共三个文件,将其放在一个文件夹中
1.驱动程序devDrv.c
2.makefile文件。注意,文件名就叫makefile或者Makefile,大小写不可随意更改,关于makefile的编写,参考
http://wiki.ubuntu.org.cn/index.php?title=%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile:MakeFile%E4%BB%8B%E7%BB%8D&variant=zh-cn
3.测试程序test.c
参考资料:
linux设备驱动程序(hello world ):http://ibeyond.blog.51cto.com/1988404/400267
linux设备驱动程序:http://www.knowsky.com/340884.html
file_operation 结构详解:http://www.chineselinuxuniversity.net/articles/45406.shtml
linux字符设备驱动程序:http://blog.csdn.net/r91987/article/details/5336974
分享到:
相关推荐
Linux 字符设备驱动程序...Linux 字符设备驱动程序学习笔记中还介绍了驱动程序的分类、字符设备驱动程序的设计、驱动程序的安装方式、设备文件的概念等知识点,为读者提供了系统的 Linux 字符设备驱动程序学习资源。
### Linux字符设备驱动程序详解 #### 一、概述 在Linux系统中,设备驱动程序是操作系统与硬件设备之间的重要桥梁,负责实现操作系统对硬件设备的访问。根据设备数据传输方式的不同,Linux设备主要分为三类:字符...
本文将详细讲解如何在Linux 2.4内核版本下编写简单的字符设备驱动程序,并涵盖相关的核心概念和技术。 首先,我们要了解字符设备驱动的基本结构。在Linux中,每个设备都对应一个设备文件,它位于`/dev`目录下。字符...
### 基于Linux的字符设备驱动程序设计 #### 一、引言 在现代操作系统中,设备驱动程序是连接硬件与软件的关键桥梁。Linux操作系统以其开放性与灵活性著称,支持广泛的硬件设备,其中字符设备驱动作为一种重要的...
本文将深入探讨“Linux字符设备驱动实例”,并解析如何自动生成设备文件于`/sys`和`/dev`目录下。 首先,我们要理解字符设备驱动的基本结构。在Linux中,字符设备驱动通常基于字符设备文件模型,它由设备号(major...
Linux字符设备驱动程序是一种在Linux操作系统中,为特定硬件设备提供的软件程序,它为用户层的应用程序提供了一组标准化的接口,使得这些程序能够控制硬件而无需了解硬件工作细节。Linux内核中的驱动程序运行在内核...
总结一下,Linux字符设备驱动程序的学习涵盖以下关键点: 1. 设备模型理解:掌握字符设备和块设备的区别,了解设备号的含义。 2. `file_operations`结构体:熟悉其包含的各种操作函数及其用法。 3. 设备注册与注销...
本文深入探讨了Linux字符设备驱动程序的核心设计原理,包括如何创建设备、初始化设备、分配设备资源以及如何访问这些设备的具体方法。通过详细介绍相关的函数实现过程,帮助读者更好地理解并掌握字符设备驱动程序的...
本篇文章将深入讲解Linux字符设备驱动程序的原理和实现方法。 首先,Linux将设备分为两类:字符设备和块设备。字符设备以字符流的形式传输数据,例如键盘、串口等;而块设备则是以块为单位进行数据传输,如硬盘、...
本文档为Linux下最简单的字符设备驱动程序
### Linux下字符设备驱动程序的结构 #### 一、概览 在Linux操作系统中,字符设备驱动程序是一种特殊的软件组件,它负责管理那些不支持随机访问的设备,如串行端口、打印机等。这些设备通常被视为文件系统中的特殊...
我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把下面的C代码输入机器,你就会获得一个真正的设备驱动程序。 #define __NO_VERSION__ #include ...
在Linux中,设备驱动通常分为字符设备驱动、块设备驱动和网络设备驱动等类型。这些驱动程序允许操作系统执行如读写数据、配置设备参数等操作。 二、ARM架构与6410处理器 ARM(Advanced RISC Machines)架构是一种...
操作系统课程设计—Linux字符设备驱动程序是学习操作系统底层机制的重要实践环节,特别是对那些希望深入理解Linux内核的开发者来说,具有极高的学习价值。字符设备驱动程序是连接硬件和操作系统之间的桥梁,它负责...
在Linux系统下,字符设备驱动可以分为三个部分:设备驱动模块、设备操作接口和字符设备驱动程序。设备驱动模块是指加载到内核中的设备驱动程序,负责将设备的操作请求传递给设备操作接口。设备操作接口是指用于与...
在Linux系统中,添加字符设备驱动程序是扩展操作系统与硬件交互能力的重要步骤。字符设备驱动程序通常处理一对一的通信,即一个设备对应一个文件描述符,适用于串行端口、键盘、鼠标等设备。本教程将详细介绍如何在...
linux 添加字符设备驱动程序及测试程序,linux下采用模块方法,添加一个新的设备驱动程序。要求添加字符设备的驱动。另附一个应用程序,测试添加的驱动程序. int main(void) { int fd; char buf[MAX_SIZE]; char ...
总结来说,添加Linux字符设备驱动程序涉及创建设备文件、编写驱动代码、注册驱动、编译加载驱动以及编写测试应用。这个过程中,理解和掌握Linux内核机制、设备驱动原理以及C语言编程是必不可少的。通过这样的实践,...