首页 Linux设备驱动程序框架

Linux设备驱动程序框架

举报
开通vip

Linux设备驱动程序框架 Linux 设备驱动程序框架 一、linux 的设备驱动程序与外界的接口可以分为三个部分: 1.驱动程序与操作系统内核的接口。通过 file_operations(include/linux/fs.h)数据 结构来完成的。 2.驱动程序与系统引导的接口。这部分利用驱动程序对设备进行初始化。 3.驱动程序与设备的接口。这部分描述了驱动程序如何与设备进行交互,与具体的设备 密切相关。 二、根据功能划分,设备驱动程序的代码有以下几部分: ...

Linux设备驱动程序框架
Linux 设备驱动程序框架 一、linux 的设备驱动程序与外界的接口可以分为三个部分: 1.驱动程序与操作系统内核的接口。通过 file_operations(include/linux/fs.h)数据 结构来完成的。 2.驱动程序与系统引导的接口。这部分利用驱动程序对设备进行初始化。 3.驱动程序与设备的接口。这部分描述了驱动程序如何与设备进行交互,与具体的设备 密切相关。 二、根据功能划分,设备驱动程序的代码有以下几部分: 1.驱动程序的注册和注销。 2.设备的打开和释放。 3.设备的读写操作。 4.设备的控制操作。 5.设备的中断和轮询处理。 三、驱动程序的注册和注销: 设备驱动程序可以在系统启动的时候初始化,也可以在需要的时候动态加载。字符设备 的 初 始 化 由 chr_dev_init() 完 成 , 包 括 对 内 存 (devfs_register_chrdev(MEM_MAJOR,"mem",&memory_fops)),终端(tty_init()),打印机 (lp_init()),鼠标(misc_init())等字符设备的初始化。 块设备初始化由 blk_dev_init()完成,这包括对 IDE 硬盘(ide_init()),软盘 (floppy_init()),光驱等块设备的初始化。 每个字符设备或是块设备的初始化都是通过 devfs_register_chrdev() 或是 devfs_register_blkdev()向内核注册。在关闭字符设备或是块设备时,还需要通过 devfs_unregister_chrdev()或是 devfs_unregister_blkdev()从内核中注销设备。 四、设备的打开和释放: 打开设备是由 open()来完成的。例如,打印机是用 lp_open()打开的,而硬盘是用 hd_open()打开的。在大部分设备驱动程序中,open 完成如下工作: 1.增加设备的是用计数。 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 2.检查设备的相关错误,如设备尚未准备好或是类似硬件的问题。 3.检查是首次打开,则初始化设备。 4.识别次设备号,如有必要则更新 f_op 指针。 5.如果需要,分配且设置要放在 filp->private_data 里的数据结构。 释放设备由 release()来完成,例如释放打印机是用 lp_release(),而释放终端设备是 用 tty_release()。释放设备的一般步骤包括: 1.释放在 filp->private_data 中的 open 分配的内存。 2.如果是最后一次释放,则关闭设备。 3.递减设别的使用计数。 五、设备的读写操作: 字符设备使用各自的 read()和 write()来进行数据读写。例如,对虚拟终端的读写是通 过 vcs_read()和 vcs_write()来进行数据读写的。 块设备使用通用的 generic_file_read()和 generic_file_write()来进行数据读写。这两个 通用函数向请求表添加读写请求,内核可以通过 ll_rw_block()优化请求顺序。由于是对内 存缓冲区而不是设备进行操作的,因而可以加快读写请求。如果内存缓冲区内没有要读入的 数据或是要将写请求写入设备,那么就要真正的执行数据传输。这是通过数据结构 request_queue 和 request_fn()来完成(include/linux/blkdev.h)。 六、设备的控制操作: 除了读写操作,有时还要控制设备。这可以通过设备驱动程序中的 ioctl()来完成。例 如 IDE 硬盘的控制可以通过 hd_ioctl(),对光驱的控制可以通过 cdrom_ioctl()。 与读写操作不同,ioctl()的用法与具体设备密切相关。以软驱的 floppy_ioctl()为例 (drivers/block/floppy.c): static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long param); 其中,cmd 的取值及含义都是与软驱有关的,比如,FDEJECT 表示弹出软盘。 除了 ioctl(),设备驱动程序还可能有其他控制函数,比如 llseek()等。 七、设备的轮询和中断处理: 对于不支持中断的设备,读写时需要轮询设备状态,以及是否需要继续进行数据传输。 例如,打印机。如果设备支持中断,则可按照中断方式进行。 由于嵌入式设备由于硬件种类非常丰富,在默认的内核发布版中不一定包括所有驱动程序。 所以进行嵌入式 Linux 系统的开发,很大的工作量是为各种设备编写驱动程序。除非系统不 使用操作系统,程序直接操纵硬件。嵌入式 Linux 系统驱动程序开发与普通 Linux 开发没有 区别。可以在硬件生产厂家或者 Internet 上寻找驱动程序,也可以根据相近的硬件驱动程序 来改写,这样可以加快开发速度。实现一个嵌入式 Linux 设备驱动的大致流程如下: (1)查看原理图,理解设备的工作原理。一般嵌入式处理器的生产商提供参考电路,也可以 根据需要自行设计。 (2)定义设备号。设备由一个主设备号和一个次设备号来标识。主设备号惟一标识了设备类 型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设 备驱动程序解释,区分被一个设备驱动控制下的某个独立的设备。 (3)实现初始化函数。在驱动程序中实现驱动的注册和卸载。 (4)设计所要实现的文件操作,定义 file_operations 结构。 (5)实现所需的文件操作调用,如 read、write 等。 (6)实现中断服务,并用 request_irq 向内核注册,中断并不是每个设备驱动所必需的。 (7)编译该驱动程序到内核中,或者用 insmod 命令加载模块。 (8)测试该设备,编写应用程序,对驱动程序进行测试 包括设备注册在内,设备驱动的初始化函数主要完成的功能是有以下 5项。 (1)对驱动程序管理的硬件进行必要的初始化。 对硬件寄存器进行设置。比如,设置中断掩码,设置串口的工作方式、并口的数据方向等。 (2)初始化设备驱动相关的参数。 一般说来,每个设备都要定义一个设备变量,用以保存设备相关的参数。在这一步骤里对设 备变量中的项进行初始化。 (3)在内核注册设备。 调用 register_chrdev()函数来注册设备。 (4)注册中断。 如果设备需要 IRQ 支持,则要使用 request_irq()函数注册中断。 (5)其他初始化工作。 初始化部分一般还负责给设备驱动程序申请包括内存、时钟、I/O 端口等在内的系统资源, 这些资源也可以在 open 子程序或者其他地方申请。这些资源不用时,应该释放,以利于资源 的共享。 若驱动程序是内核的一部分,初始化函数则要按如下方式声明: int __init chr_driver_init(void); Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 其中__init 是必不可少的,在系统启动时会由内核调用 chr_driver_init,完成驱动程序的 初始化。 当驱动程序是以模块的形式编写时,则要按照如下方式声明: int init_module(void) 当运行后面介绍的 insmod 命令插入模块时,会调用 init_module 函数完成初始化工作。 设备驱动开发的基本函数: 1.I/O 口函数 无论驱动程序多么复杂,归根结底,无非还是向某个端口或者某个寄存器位赋值,这个值只 能是 0 或 1。接收值的就是 I/O 口。与中断和内存不同,使用一个没有申请的 I/O 端口不会 使处理器产生异常,也就不会导致诸如“segmentation fault”一类的错误发生。由于任何 进程都可以访问任何一个 I/O 端口,此时系统无法保证对 I/O 端口的操作不会发生冲突,甚 至因此而使系统崩溃。因此,在使用 I/O 端口前,也应该检查此 I/O 端口是否已有别的程序 在使用,若没有,再把此端口标记为正在使用,在使用完以后释放它。 这样需要用到如下几个函数: int check_region(unsigned int from, unsigned int extent); void request_region(unsigned int from, unsigned int extent,const char *name); void release_region(unsigned int from, unsigned int extent); 调用这些函数时的参数为: ? from 表示所申请的 I/O 端口的起始地址; ? extent 为所要申请的从 from 开始的端口数; ? name 为设备名,将会出现在/proc/ioports 文件里; ? check_region 返回 0表示 I/O 端口空闲,否则为正在被使用。 在申请了 I/O 端口之后,可以借助 asm/io.h 中的如下几个函数来访问 I/O 端口: inline unsigned int inb(unsigned short port); inline unsigned int inb_p(unsigned short port); inline void outb(char value, unsigned short port); inline void outb_p(char?value, unsigned short port); 其中 inb_p 和 outb_p 插入了一定的延时以适应某些低速的 I/O 端口。 2.时钟函数 在设备驱动程序中,一般都需要用到计时机制。在 Linux 系统中,时钟是由系统接管的,设 备驱动程序可以向系统申请时钟。与时钟有关的系统调用有: #include #include void add_timer(struct timer_list * timer); int del_timer(struct timer_list * timer); inline void init_timer(struct timer_list * timer); struct timer_list 的定义为: struct timer_list { struct timer_list *next; struct timer_list *prev; Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 unsigned long expires; unsigned long data; void (*function)(unsigned long d); }; 其中,expires 是要执行 function 的时间。系统核心有一个全局变量 jiffies 表示当前时间, 一般在调用 add_timer 时 jiffies=JIFFIES+num,表示在 num 个系统最小时间间隔后执行 function 函数。系统最小时间间隔与所用的硬件平台有关,在核心里定义了常数 HZ 表示一 秒内最小时间间隔的数目,则 num*HZ 表示 num 秒。系统计时到预定时间就调用 function, 并把此子程序从定时队列里删除,可见,如果想要每隔一定时间间隔执行一次的话,就必须 在 function 里再一次调用 add_timer。function 的参数 d 即为 timer 里面的 data 项。 3.内存操作函数 作为系统核心的一部分,设备驱动程序在申请和释放内存时不是调用 malloc 和 free,而代 之以调用 kmalloc 和 kfree,它们在 linux/kernel.h 中被定义为: void * kmalloc(unsigned int len, int priority); void kfree(void * obj); 参数 len 为希望申请的字节数,obj 为要释放的内存指针。priority 为分配内存操作的优先 级,即在没有足够空闲内存时如何操作,一般由取值 GFP_KERNEL 解决即可。 4.复制函数 在用户程序调用 read、write 时,因为进程的运行状态由用户态变为核心态,地址空间也变 为核心地址空间。由于 read、write 中参数 buf 是指向用户程序的私有地址空间的,所以不 能直接访问,必须通过下面两个系统函数来访问用户程序的私有地址空间。 #include void memcpy_fromfs(void * to,const void * from,unsigned long n); void memcpy_tofs(void * to,const void * from,unsigned long n); memcpy_fromfs 由用户程序地址空间往核心地址空间复制,memcpy_tofs 则反之。参数 to为 复制的目的指针,from 为源指针,n为要复制的字节数。 在设备驱动程序里,可以调用 printk 来打印一些调试信息,printk 的用法与 printf 类似。 printk 打印的信息不仅出现在屏幕上,同时还记录在文件 syslog 里。 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔 Administrator 铅笔
本文档为【Linux设备驱动程序框架】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_003817
暂无简介~
格式:pdf
大小:195KB
软件:PDF阅读器
页数:5
分类:互联网
上传时间:2012-03-18
浏览量:30