如何编写Linux设备驱动程序
[驱动] 如何编写Linux设备驱动程序
Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。
以下的一些文字主要来源于khg,johnsonm的Write linux device driver,Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关device driver的一些资料。
一、Linux device driver 的概念
系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:
1。对设备初始化和释放。
2。把数据从内核传送到硬件和从硬件读取数据。
3。读取应用程序传送给设备文件的数据和回送应用程序请求的数据。
4。检测和处理设备出现的错误。
在Linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。
已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。
最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。 读/写时,它首先察看缓冲区的内容,如果缓冲区的数据
如何编写Linux操作系统下的设备驱动程序
[驱动] 如何编写Linux设备驱动程序
二、实例剖析
我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把下面的C代码输入机器,你就会获得一个真正的设备驱动程序。 1. #define __NO_VERSION__
2. #include <linux/modules.h>
3. #include <linux/version.h>
4. char kernel_version [] = UTS_RELEASE;
复制代码
这一段定义了一些版本信息,虽然用处不是很大,但也必不可少。Johnsonm说所有的驱动程序的开头都要包含<linux/config.h>,一般来讲最好使用。
由于用户进程是通过设备文件同硬件打交道,对设备文件的操作方式不外乎就是一些系统调用,如 open,read,write,close…, 注意,不是fopen, fread,但是如何把系统调用和驱动程序关联起来呢?这需要了解一个非常关键的数据结构: 1. struct file_operations
2. {
3. int (*seek) (struct inode * ,struct file *, off_t ,int);
4. int (*read) (struct inode * ,struct file *, char ,int);
5. int (*write) (struct inode * ,struct file *, off_t ,int);
6. int (*readdir) (struct inode * ,struct file *, struct dirent * ,
int);
7. int (*select) (struct inode * ,struct file *, int ,select_table *);
8. int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned
long);
9. int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);
10. int (*open) (struct inode * ,struct file *);
11. int (*release) (struct inode * ,struct file *);
12. int (*fsync) (struct inode * ,struct file *);
13. int (*fasync) (struct inode * ,struct file *,int);
14. int (*check_media_change) (struct inode * ,struct file *);
15. int (*revalidate) (dev_t dev);
16. }
[驱动] 如何编写Linux设备驱动程序
复制代码
这个结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。既然是这样,则编写设备驱动程序的主要工作就是编写子函数,并填充file_operations的各个域。
下面就开始写子程序。 1. #include <linux/types.h> 2. #include <linux/fs.h>
3. #include <linux/mm.h>
4. #include <linux/errno.h>
5. #include <asm/segment.h>
6. unsigned int test_major = 0;
7. static int read_test(struct inode *node,struct file *file,char *buf,
int count)
8. {
9. int left;
10. if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )
11. return -EFAULT;
12. for(left = count ; left > 0 ; left--)
13. {
14. __put_user(1,buf,1);
15. buf++;
16. }
17. return count;
18. }
复制代码
这个函数是为read调用准备的。当调用read时,read_test()被调用,它把用户的缓冲区全部写1。buf 是read调用的一个参数。它是用户进程空间的一个地址。但是在read_test被调用时,系统进入核心态。所以不能使用buf这个地址,必须用__put_user(),这是kernel
[驱动] 如何编写Linux设备驱动程序
提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数。请参考,在向用户空间拷贝数据之前,必须验证buf是否可用。这就用到函数verify_area。 1. static int write_tibet(struct inode *inode,struct file *file,const
char *buf,int count)
2. {
3. return count;
4. }
5.
6. static int open_tibet(struct inode *inode,struct file *file )
7. {
8. MOD_INC_USE_COUNT;
9. return 0;
10. }
11.
12. static void release_tibet(struct inode *inode,struct file *file )
13. {
14. MOD_DEC_USE_COUNT;
15. }
复制代码
这几个函数都是空操作。实际调用发生时什么也不做,他们仅仅为下面的结构提供函数指针。
1. struct file_operations test_fops = {
相关推荐:
- [实用模板]第八章:法国“新浪潮”与“左岸派”
- [实用模板]2021年北京上半年临床医学检验技师生物
- [实用模板]SAP GUI 7.10客户端安装配置文档
- [实用模板]2001年临床执业医师资格考试综合笔试试
- [实用模板]36机场工作实用英语词汇总结
- [实用模板](一)社会保险稽核通知书
- [实用模板]安全教育主题班会材料
- [实用模板]濉溪县春季呼吸道传染病防控应急演练方
- [实用模板]长沙房地产市场周报(1.30-2.3)
- [实用模板]六年级数学上册典中点 - 图文
- [实用模板]C程序设计(红皮书)习题官方参考答案
- [实用模板]中国证监会第一届创业板发行审核委员会
- [实用模板]桥梁工程复习题
- [实用模板]2011学而思数学及答案
- [实用模板]初中病句修改专项练习
- [实用模板]监理学习知识1 - 图文
- [实用模板]小机灵杯四年级试题
- [实用模板]国贸专业毕业论文模板
- [实用模板]教育学概论考试练习题-判断题4
- [实用模板]2015届高考英语一轮复习精品资料(译林
- 00Nkmhe_市场营销学工商管理_电子商务_
- 事业单位考试法律常识
- 诚信教育实施方案
- 吉大小天鹅食品安全检测箱方案(高中低
- 房地产销售培训资料
- 高一地理必修1复习提纲
- 新概念英语第二册lesson_1_练习题
- 证券公司内部培训资料
- 小学英语时间介词专项练习
- 新世纪英语专业综合教程(第二版)第1册U
- 【新课标】浙教版最新2018年八年级数学
- 工程建设管理纲要
- 外研版 必修一Module 4 A Social Surve
- Adobe认证考试 AE复习资料
- 基于H.264AVC与AVS标准的帧内预测技术
- 《食品检验机构资质认定管理办法》(质
- ABB变频器培训课件
- (完整版)小学说明文阅读练习题及答案
- 深思洛克(SenseLock) 深思IV,深思4,深
- 弟子规全文带拼音




