2022年如何编写驱动程序 .pdf
《2022年如何编写驱动程序 .pdf》由会员分享,可在线阅读,更多相关《2022年如何编写驱动程序 .pdf(5页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、如何编写 Linux 设备驱动程序 Linux 是 Unix 操作系统的一种变种, 在 Linux下编写驱动程序的原理和思想完全类似于其他的Unix 系统,但它 dos 或 window环境下的驱动程序有很大的区别。在 Linux 环境下设计驱动程序, 思想简洁, 操作方便,功能也很强大,但是支持函数少,只能依赖kernel 中的函数,有些常用的操作要自己来编写,而且调试也不方便。以下的一些文字主要来源于khgjohnsonm 的 Write linux device driver, Brennans Guide to Inline AssemblyThe Linux A-Z ,还有清华 BB
2、S上的有关 device driver的一些资料。一、Linux device driver 的概念系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。 设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来, 硬件设备只是一个设备文件, 应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能: 1。对设备初始化和释放。2。把数据从内核传送到硬件和从硬件读取数据。3。读取应用程序传送给设备文件的数据和回送应用程序请求的数据。4。检测和处理设备出现的错误。在 Linux 操作系统下有三类主要的设备文件类型,一是字
3、符设备, 二是块设备,三是网络设备。 字符设备和块设备的主要区别是: 在对字符设备发出读 / 写请求时,实际的硬件 I/O 一般就紧接着发生了, 块设备则不然, 它利用一块系统内存作缓冲区, 当用户进程对设备请求能满足用户的要求,就返回请求的数据, 如果不能,就调用请求函数来进行实际的I/O 操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU 时间来等待。已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性 (c/b) , 表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程
4、序的不同的硬件设备,比如有两个软盘, 就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。最后必须提到的是, 在用户进程调用驱动程序时, 系统进入核心态, 这时不再是抢先式调度。 也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的 fsck 。读/ 写时,它首先察看缓冲区的内容,如果缓冲区的数据如何编写 Linux 操作系统下的设备驱动程序二、实例剖析我们来写一个最简单的字符设备驱动程序。虽然它什么也不做, 但是通过它可以了解 Li
5、nux 的设备驱动程序的工作原理。 把下面的 C代码输入机器, 你就会获得一个真正的设备驱动程序。#define _NO_VERSION_ #include #include char kernel_version = UTS_RELEASE; 这一段定义了一些版本信息, 虽然用处不是很大, 但也必不可少。 Johnsonm名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 5 页 - - - - - - - - - 说所有的驱动程序的开头都要包含,一般来讲最好使用。由于用户
6、进程是通过设备文件同硬件打交道,对设备文件的操作方式不外乎就是一些系统调用, 如 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
7、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
8、 *); 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); 这个结构的每一个成员的名字都
9、对应着一个系统调用。用户进程利用系统调用在对设备文件进行诸如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序, 然后读取这个数据结构相应的函数指针,接着把控制权交给该函数。 这是 linux的设备驱动程序工作的基本原理。既然是这样, 则编写设备驱动程序的主要工作就是编写子函数,并填充 file_operations的各个域。下面就开始写子程序。#include #include #include #include #include unsigned int test_major = 0; static int read_test(struct inode *no
10、de,struct file *file,char *buf ,int count) int left; if (verify_area(VERIFY_WRITE,buf , count) = 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 5 页 - - - - - - - - - -EFAULT ) return -EFAULT; for(left = count ; left 0 ; left-) _put_user(1,buf ,1); buf+; return
11、count; 这个函数是为 read 调用准备的。当调用read 时,read_test()被调用,它把用户的缓冲区全部写1。buf 是 read 调用的一个参数。 它是用户进程空间的一个地址。 但是在 read_test被调用时,系统进入核心态。 所以不能使用 buf 这个地址,必须用 _put_user() ,这是 kernel提供的一个函数,用于向用户传送数据。另外还有很多类似功能的函数。请参考,在向用户空间拷贝数据之前,必须验证buf 是否可用。这就用到函数 verify_area。 static int write_tibet(struct inode *inode , struct
12、 file *file, const char *buf , int count) return count; static int open_tibet(struct inode *inode ,struct file *file ) MOD_INC_USE_COUNT; return 0; static void release_tibet(struct inode *inode,struct file *file ) MOD_DEC_USE_COUNT; 这几个函数都是空操作。 实际调用发生时什么也不做, 他们仅仅为下面的结构提供函数指针。 struct file_operations
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年如何编写驱动程序 2022 如何 编写 驱动程序
限制150内