ImageVerifierCode 换一换
格式:DOC , 页数:7 ,大小:56.50KB ,
资源ID:7679624      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/7679624.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(Linux字符设备驱动程序编写基本流程.doc)为本站上传会员【xrp****65】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

Linux字符设备驱动程序编写基本流程.doc

1、Linux字符设备驱动程序编写基本流程 Linux device driver 的概念   系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1、对设备初始化和释放; 2、把数据从内核传送到硬件和从硬件读取数据; 3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据; 4、检测和处理设备出现的错误。   在Linu

2、x操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。   已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号

3、标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。 1.Linux驱动程序编写基本流程: 1.首先是一些版本信息,没什么用,但是不能少 #define __NO_VERSION__ #include #include char kernel_version[] = UTS_RELEASE; 2.为了把系统调用和驱动程序关联起来,需要一个非常关键的数据结构:struc

4、t file_operations。file_operations结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。编写设备驱动程序的主要工作就是编写子函数,并填充file_operations的各个域 3.简单驱动程序的编写(test.c): a.包含一些基本的头文件。 b.编写一些功能函数,比如read(),write()等。这些函数被调用时系统进入和心态。 c.定

5、义struct file_operations结构的对象,填充结构体。结构体中功能的顺序不能改变,若一些功能没有实现就用NULL填充,已经实现的功能如read()、write()分别添加到对应的位置。这步实现的是函数的注册。到这里驱动程序的主体可以说是写好了。现在需要把驱动程序嵌入内核。 d.注册设备驱动程序,使用register_chrdev注册字符型设备。函数原型为: int register_chrdev(0, “test_name”, &test_file_operations) 函数返回主设备号,若注册成功返回值大于0。 第一个参数:主设备号。第二个参数:注册的设备名。第三个

6、参数:结构体名(设备相关操作方式,驱动程序实际执行操作的函数的指针)。 这个函数由int init_module(void)函数调用,这个函数在系统启动时注册到内核时调用。 e.在用rmmod卸载模块时,cleanup_module函数被调用,它释放字符设备test在系统字符设备表中占有的表项。 void cleanup_module(void) { unregister_chrdev(test_major, “test”); } 到这里test.c基本就编写完成了。一个简单的字符设备可以说写好了。 4.编译 $ gcc -O2 -DMODULE -D__KERNEL__ -

7、c test.o test.c 得到文件test.o就是一个设备驱动程序。 如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后 ld -r file1.o file2.o -o modulename 驱动程序已经编译好了,现在把它安装到系统中去。 $ insmod -f test.o 安装成功在/proc/devices文件中就可以看到设备test,并可以看到主设备号。要卸载运行: $ rmmod test 5.创建设备节点 mkmod /dev/test c major minor c是指字符设备,major是主设备号,minor是从设备号,一般可以设置为0

8、 以上就是Linux驱动编写的基本过程了,可能有遗漏的地方,这个我只是按我理解的整理的。具体问题还要在实践中再进行研究。 1.Linux驱动程序编写基本流程: 1.首先是一些版本信息,没什么用,但是不能少 #define __NO_VERSION__ #include #include char kernel_version[] = UTS_RELEASE;  2.为了把系统调用和驱动程序关联起来,需要一个非常关键的数据结构:struct file_operations。file_operations结构的每一

9、个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。编写设备驱动程序的主要工作就是编写子函数,并填充file_operations的各个域 3.简单驱动程序的编写(test.c): a.包含一些基本的头文件。 b.编写一些功能函数,比如read(),write()等。这些函数被调用时系统进入和心态。 c.定义struct file_operations结构的对象,填充结构体。结构体

10、中功能的顺序不能改变,若一些功能没有实现就用NULL填充,已经实现的功能如read()、write()分别添加到对应的位置。这步实现的是函数的注册。到这里驱动程序的主体可以说是写好了。现在需要把驱动程序嵌入内核。 d.注册设备驱动程序,使用register_chrdev注册字符型设备。函数原型为: int register_chrdev(0, “test_name”, &test_file_operations) 函数返回主设备号,若注册成功返回值大于0。 第一个参数:主设备号。第二个参数:注册的设备名。第三个参数:结构体名(设备相关操作方式,驱动程序实际执行操作的函数的指针)。 这

11、个函数由int init_module(void)函数调用,这个函数在系统启动时注册到内核时调用。e.在用rmmod卸载模块时,cleanup_module函数被调用,它释放字符设备test在系统字符设备表中占有的表项。 void cleanup_module(void) { unregister_chrdev(test_major, “test”); } 到这里test.c基本就编写完成了。一个简单的字符设备可以说写好了。  4.编译 $ gcc -O2 -DMODULE -D__KERNEL__ -c test.o test.c 得到文件test.o就是一个设备驱动程序。

12、如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后 ld -r file1.o file2.o -o modulename 驱动程序已经编译好了,现在把它安装到系统中去。 $ insmod -f test.o 安装成功在/proc/devices文件中就可以看到设备test,并可以看到主设备号。要卸载运行: $ rmmod test 5.创建设备节点 mkmod /dev/test c major minor c是指字符设备,major是主设备号,minor是从设备号,一般可以设置为0 以上就是Linux驱动编写的基本过程了,可能有遗漏的地方,这个我只是按我理解的

13、整理的。具体问题还要在实践中再进行研究。 二、实例剖析   我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。把下面的C代码输入机器,你就会获得一个真正的设备驱动程序。   由于用户进程是通过设备文件同硬件打交道,对设备文件的操作方式不外乎就是一些系统调用,如 open,read,write,close…, 注意,不是fopen, fread,但是如何把系统调用和驱动程序关联起来呢?这需要了解一个非常关键的数据结构: struct file_operations { int (*seek) (struct

14、 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 *);

15、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 (*f

16、async) (struct inode * ,struct file *,int); int (*check_media_change) (struct inode * ,struct file *); int (*revalidate) (dev_t dev); }   这个结构的每一个成员的名字都对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。既然是这样,则编写设备驱动程序

17、的主要工作就是编写子函数,并填充file_operations的各个域。   下面就开始写子程序。 #include 基本的类型定义 #include 文件系统使用相关的头文件 #include #include #include unsigned int test_major = 0; static int read_test(struct inode *inode,struct file *file,char

18、 *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; }   这个函数是为read调用准备的。当调用read时,read_test()被调用,它把用户的缓冲区全部写1。buf 是read调用的一个参数。它是用户进程空间

19、的一个地址。但是在read_test被调用时,系统进入核心态。所以不能使用buf这个地址,必须用__put_user(),这是kernel提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数。请参考,在向用户空间拷贝数据之前,必须验证buf是否可用。这就用到函数verify_area。为了验证BUF是否可以用。 static int write_test(struct inode *inode,struct file *file,const char *buf,int count) { return count; } static int open_test(

20、struct inode *inode,struct file *file ) { MOD_INC_USE_COUNT; 模块计数加以,表示当前内核有个设备加载内核当中去 return 0; } static void release_test(struct inode *inode,struct file *file ) { MOD_DEC_USE_COUNT; }   这几个函数都是空操作。实际调用发生时什么也不做,他们仅仅为下面的结构提供函数指针。 struct file_operations test_fops = {? read_tes

21、t, write_test, open_test, release_test, };   设备驱动程序的主体可以说是写好了。现在要把驱动程序嵌入内核。驱动程序可以按照两种方式编译。一种是编译进kernel,另一种是编译成模块(modules),如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以推荐使用模块方式。 int init_module(void) { int result; result = register_chrdev(0, "test", &test_fops); 对设备操作的整个接口

22、if (result < 0) { printk(KERN_INFO "test: can't get major number\n"); return result; } if (test_major == 0) test_major = result; /* dynamic */ return 0; }   在用insmod命令将编译好的模块调入内存时,init_module 函数被调用。在这里,init_module只做了一件事,就是向系统的字符设备表登记了一个字符设备。register_chrdev需要三个参数,参数一是希望获得的设备号,如果是零的话,系

23、统将选择一个没有被占用的设备号返回。参数二是设备文件名,参数三用来登记驱动程序实际执行操作的函数的指针。   如果登记成功,返回设备的主设备号,不成功,返回一个负值。 void cleanup_module(void) { unregister_chrdev(test_major,"test"); }   在用rmmod卸载模块时,cleanup_module函数被调用,它释放字符设备test在系统字符设备表中占有的表项。   一个极其简单的字符设备可以说写好了,文件名就叫test.c吧。   下面编译 : $ gcc -O2 -DMOD

24、ULE -D__KERNEL__ -c test.c –c表示输出制定名,自动生成.o文件 得到文件test.o就是一个设备驱动程序。 如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后 ld ?-r ?file1.o ?file2.o ?-o ?modulename。 驱动程序已经编译好了,现在把它安装到系统中去。 $ insmod ?–f ?test.o 如果安装成功,在/proc/devices文件中就可以看到设备test,并可以看到它的主设备号。要卸载的话,运行 : $ rmmod test 下一步要创建设备文

25、件。 mknod /dev/test c major minor c 是指字符设备,major是主设备号,就是在/proc/devices里看到的。 用shell命令 $ cat /proc/devices 就可以获得主设备号,可以把上面的命令行加入你的shell script中去。 minor是从设备号,设置成0就可以了。 我们现在可以通过设备文件来访问我们的驱动程序。写一个小小的测试程序。 #include #include #include #

26、include main() { int testdev; int i; char buf[10]; testdev = open("/dev/test",O_RDWR); if ( testdev == -1 ) { printf("Cann't open file \n"); exit(0); } read(testdev,buf,10); for (i = 0; i < 10;i++) printf("%d\n",buf[i]); close(testdev); } 编译运行,看看是不是打印出全1 ?   以上只是一个简单的演示。真正实用的驱动程序要复杂的多,要处理如中断,DMA,I/O port等问 本文来自CSDN博客,转载请标明出处:

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服