开发工具:
文件大小: 198kb
下载次数: 0
上传时间: 2019-06-29
详细说明:
字符设备驱动编写流程,对设备初始化和释放;
2、把数据从内核传送到硬件和从硬件读取数据;
3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据;
4、检测和处理设备出现的错误些功能没有实现就用NULL填充,已经实现的功能如read0、 write分别添加到对应的位置
这步实现的是函数的注册。到这里驱动程序的主体可以说是写好了。现在需要把驱动程序嵌
入内核。
d注册设备驱动程序,使用 register_chrdev注册字符型设备。函数原型为
int register chrdevo,test_name", &test_file_ operations
函数返回主设备号,若注册成功返回值大于0。
第一个参数:主设备号。第二个参数:注册的设备名。第三个参数:结构体名(设备相关操
作方式,驱动程序实际执行操作的函数的指针)。
这个函数由 int init module(oid)函数调用,这个函数在系统启动时注册到内核时调用。e在
用mmod卸载模块时, cleanup_module函数被调用,它释放字符设备test在系统字符设备
表中占有的表项
void cleanup_module(void)
unregister chrdevtest major,test
到这里 test.c基本就编写完成了。一个简单的字符设备可以说写好了。4编译
S gcc-02-DMODULE-DKERNEL-c test o test. c
得到文件test就是一个设备驱动程序。
如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后
d-r file1. o file2.0-o modulename
驱动程序巳经编译好了,现在把它安装到系统中去。
S insmod-f test o
安装成功在/proc/ devices文件中就可以看到设备test,并可以看到主设备号。要卸载运行
S rmmod test
5创建设备节点
mkmod /dev/test c major minor
C是指字符设备,maor是主设备号, minor是从设备号,一般可以设置为0
以上就是 Linux驱动编写的基本过程了可能有遗漏的地方,这个我只是按我理解的整理的。
具体问题还要在实践中冉进行研究
二、实例剖析
我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解
Linux的设备驱动程序的工作原理。把下面的C代码输入机器,你就会获得一个真正的设各
驱动程序。
由于用户进程是通过设备文件同硬件打交道,对设备文件的操作方式不外乎就是一些系
统调用,如open,read, write, close…,注意,不是 fopen,fead,但是如何把系统调
用和驱动程序关联起来呢?这需要了解一个非常关键的数据结构
struct file_operations f
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(*ioct)(struct inode*, struct file*, unsined int, unsigned long)
int(*mmap)(struct inode x, struct file *, struct vm_area_struct *);
nt (*open)(struct index, struct file
int (*release)(struct inode * struct file *)
int(大synC)( struct inode大, struct file*);
int(*fasync)(struct inode *, struct file*, int)
nt(*check_media_change)(struct inode x, struct file *)
int(*revalidate)(dev t dev);
这个结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备
文件诖行诸如 read /write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程
序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是|nux的设备
驱动程序工作的基本原理。既然是这样,则编写设备驱动程序的主要工作就是编写子函数,
并填充 file_operations的各个域。
下面就开始写子程序
include基本的类型定义
nclude文件系统使用相关的头文件
#ⅰ nclude< linux/mm.h>
include
#include
unsigned int test major=0
static int read test(struct inode *inode, struct file *file, char *buf, int count
int le用户空间和内核空间
if(verify_area(VERIFY_WRITE, buf, count)==-EFAULT
return -EFAULT
for(left =count; left>0: left--
put_user(1, buf, 1)
buf++
return count
这个函数是为read调用准备的。当调用read时, read test0被调用,它把用户的缓冲
区全部写1。buf是read调用的一个参数。它是用户进程空间的一个地址。但是在 read test
被调用时,系统进入核心态。所以不能使用υuf这个地址,必须用_ put_user),这是 kernel
提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数。请参老,在向用户
空间拷贝数据之前,必须验证bu是否可用。这就用到函数 verify_area。为了验证BUF是否
可以用。
static int write test(struct inode *inode, struct file *file, const char *but, int count
return count
static int open_test(struct inode *inade, struct file *file
MOD_ NC USE COUNT;模块计数加以,表示当前内核有个设备加载内核当中去
return o
static void release__test(struct inode *inode, struct file *file
MOD DEC USE COUNT
这几个函数都是空操作。实际调用发生时什么也不做,他们仅仅为下面的结构提供函数
指针。
struct file_operations test_fops=[?
read test
write test
open_test
release test
设备驱动程序的主体可以说是写好了。现在要把驱动程序嵌入內核。驱动程序可以按照
两种方式编译。一种是编译进 kernel,另一种是编译成模块( modules),如果编译进内核的
话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以
推荐使用模块方式。
int init module(void
It result
result= register_chrdev(O,"test",& ctest_fops):对设备操作的整个接口
if (result
include≤sys/ types. h>
#include
#include
maino
nt testdev
char buf[ 10
testdev= open(/ dev/test",O_RDWR
if( testdeV ==-1)
printf("Cann't open file /n )
exit(O)
read(testdev, buf, 10)
for(=0;i<10.+
printf(%d/n", buf[)
close(testdev)
编译运行,看看是不是打印出全1?
以上只是一个简单的演示。真正实用的驱动程序要复杂的多,要处理如中断,DMA,MO
port等问
(系统自动生成,下载前可以参看下载内容)
下载文件列表
相关说明
- 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
- 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度。
- 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
- 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
- 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
- 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.