如何编写Linux的设备驱动程序
作者:Roy G
择要:比力直观地介绍了Linux设置装备摆设驱动程序的开发原理
媒介
Linux
头脑完全雷同于其他的
区别
支持函数少
试也不方便
是Unix操纵体系的一种变种,在Linux下编写驱动程序的原理和Unix体系,但它dos或window环境下的驱动程序有很大的.在Linux环境下设计驱动程序,头脑简便,操纵方便,功能也很壮大,但是,只能依赖kernel中的函数,有些常用的操纵要本身来编写,而且调.自己这几周来为实验室自行研制的一块多媒体卡体例了驱动程序,
得到了一些经验
Brennan's Guide to Inline Assembly,The Linux A-Z,
,愿与Linux fans共享,有不当之处,请予指正.以下的一些文字重要来源于khg,johnsonm的Write linux device driver,还有清华BBS上的有关
device driver
据本身的实验结果进行了修正
的一些材料. 这些材料有的已颠末期,有的还有一些错误,我依.
一
. Linux device driver 的概念
内核和呆板硬件之间的接口
在使用程序看来
一样对硬件设置装备摆设进行操纵
1.
2.
3.
4.
块设置装备摆设
的硬件
体系挪用是操纵体系内核和使用程序之间的接口,设置装备摆设驱动程序是操纵体系.设置装备摆设驱动程序为使用程序屏蔽了硬件的细节,这样,硬件设置装备摆设只是一个设置装备摆设文件, 使用程序可以象操纵普通文件.设置装备摆设驱动程序是内核的一部门,它完成以下的功能:对设置装备摆设初始化和开释.把数据从内核传送到硬件和从硬件读取数据.读取使用程序传送给设置装备摆设文件的数据和回送使用程序请求的数据.检测和处置惩罚设置装备摆设呈现的错误.在Linux操纵体系下有两类重要的设置装备摆设文件范例,一种是字符设置装备摆设,另一种是.字符设置装备摆设和块设置装备摆设的重要区别是:在对字符设置装备摆设收回读/写请求时,实际I/O一般就紧接着产生了,块设置装备摆设则不然,它利用一块体系内存作缓冲区,
当用户历程对设置装备摆设请求能满足用户的要求
的
来等待
都有其文件属性
备号
设置装备摆设驱动程序的差别的硬件设置装备摆设
他们
一致
抢先式调度
的工作
是漫长的
(
,就返回请求的数据,如果不克不及,就挪用请求函数来进行实际I/O操纵.块设置装备摆设是重要针对磁盘等慢速设置装备摆设设计的,以免泯灭过多的CPU时间.曾经提到,用户历程是经过设置装备摆设文件来与实际的硬件打交道.每个设置装备摆设文件都(c/b),表现是字符设置装备摆设还蔤强樯璞?另外每个文件都有两个设,第一个是主设置装备摆设号,标识驱动程序,第二个是从设置装备摆设号,标识利用统一个,好比有两个软盘,就可以用从设置装备摆设号来区分.设置装备摆设文件的的主设置装备摆设号必须与设置装备摆设驱动程序在注销时请求的主设置装备摆设号,否则用户历程将无法拜访到驱动程序.末了必须提到的是,在用户历程挪用驱动程序时,体系进入核心态,这时不再是.也便是说,体系必须在你的驱动程序的子函数返回后才能进行其他.如果你的驱动程序陷入去世循环,不幸的是你只有重新启动呆板了,然后就fsck.//hehe请看下节,实例剖析)
二
.实例剖析
可以相识
得到一个真正的设置装备摆设驱动程序
我们来写一个最简单的字符设置装备摆设驱动程序.固然它什么也不做,但是经过它Linux的设置装备摆设驱动程序的工作原理.把下面的C代码输出呆板,你就会.不过我的kernel是2.0.34,在低版本的kernel
上可能会呈现题目
#define __NO_VERSION__
#include
#include
char kernel_version [] = UTS_RELEASE;
,我还没测试过.//xixi
这一段界说了一些版本信息
有的驱动程序的开头都要包罗
,固然用途不是很大,但也必不行少.Johnsonm说所
由于用户历程是经过设置装备摆设文件同硬件打交道
是一些体系挪用
,对设置装备摆设文件的操纵方法不外乎就,如 open,read,write,close...., 细致,不是fopen, fread.,
但是如何把体系挪用和驱动程序关联起来呢
结构
struct file_operations {
int (*seek) (struct inode * ,struct file *, off_t ,int);
int (*read) (struct inode * ,struct file *, char ,int);
int (*write) (struct inode * ,struct file *, off_t ,int);
int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);
int (*select) (struct inode * ,struct file *, int ,select_table *);
int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long
int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);
int (*open) (struct inode * ,struct file *);
int (*release) (struct inode * ,struct file *);
int (*fsync) (struct inode * ,struct file *);
int (*fasync) (struct inode * ,struct file *,int);
int (*check_media_change) (struct inode * ,struct file *);
int (*revalidate) (dev_t dev);
}
在对设置装备摆设文件进行诸如
找到相应的设置装备摆设驱动程序
权交给该函数
设置装备摆设驱动程序的重要工作便是编写子函数
?这需要相识一个非常要害的数据:这个结构的每一个成员的名字都对应着一个体系挪用.用户历程利用体系挪用read/write操纵时,体系挪用经过设置装备摆设文件的主设置装备摆设号,然后读取这个数据结构相应的函数指针,接着把控制.这是linux的设置装备摆设驱动程序工作的基本原理.既然是这样,则编写,并添补file_operations的各个域.
相称简单
,不是吗?
下面就开端写子程序
#include
#include
#include
#include
#include
unsigned int test_major = 0;
static int read_test(struct inode *node,struct file *file,
char *buf,int count)
{
int left;
if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )
return -EFAULT;
for(left = count ; left > 0 ; left--)
{
__put_user(1,buf,1);
buf++;
}
return count;
}
.
这个函数是为
缓冲区全部写
buf
read挪用准备的.当挪用read时,read_test()被挪用,它把用户的1.是read挪用的一个参数.它是用户历程空间的一个地点.但是在read_test
被挪用时
,体系进入核心态.所以不克不及利用buf这个地点,必须用__put_user(),
这是
函数
kernel提供的一个函数,用于向用户传送数据.另外还有许多雷同功能的.请参考
- 文章作者: 福州军威计算机技术有限公司
军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。
TAG:
评论加载中...
|