Linux字符设备驱动程序开发之笔记及摘要

来源:互联网 发布:substr linux 编辑:程序博客网 时间:2024/04/27 01:47

                                                                                                                       东方绿洲  2009-12-06/21:33:36

一、Linux字符设备驱动程序   

     Linux支持3类硬件设备:字符设备、块设备及网络接口。

        字符设备指无需缓冲直接读写的设备,如系统的串口设备/dev/cua0和/dev/cual。可以像文件一样访问字符设备。字符设备和普通文件系统间的唯一区别是:普通文件允许在其上来回读写,而大多数字符设备仅是数据通道,只能顺序读取。

        设备驱动程序实际上是一些实现不同功能的函数的集合,但每一个驱动程序又都具备某些公共的函数结构,为了防止驱动程序的名称出现不协调的错误,引入了函数前缀的概念,这个函数前缀将加到驱动程序所有的函数名称前面。例如,虽然几乎所有的驱动程序都提供了open()函数,但每个驱动程序所使用的open()函数在内核中的标识是唯一的。

 

二、字符设备的相似点

         驱动程序中除了与具体设备硬件有关的内容外,其他地方可以说都是一样或类似的,其相同点大致如下:

      1、结构file_operations不仅是驱动程序中最重要的结构,也是这些相似点的核心,因为每个驱动程序提供给系统调用的接口都是一样的。

      2、每个驱动程序都会有接口函数open()、close()、read()、write()、init_module()及cleaup_module()。不管使用哪种方式访问外部设备,驱动程序中都会有这几个函数。所以字符设备驱动程序的主干都是相同的。

      3、字符设备的注册和注销采用相同的函数分别是register_chrdev()和unregister_chrdev(),甚至在使用时这两个函数中的有些参数都相同。

      4、申请中断都使用request_irq()函数,释放中断都使用free_irq()函数。

      5、产生字符设备文件都使用命令mknod/dev/*c major minor,其中参数c表示产生的是字符设备文件。

      6、都可以使用模块化编程思想,驱动程序初始化函数都是init_module(),退出函数都是cleanup_module()。

       

三、主设备号和次设备号

      字符设备由一个主设备号和一个次设备号标识。主设备号标识设备对应的驱动程序,内核利用主设备号将设备与相应的驱动程序对应起来。次设备号只由设备驱动程序使用,内核的其他部分不使用它,仅将它传递给驱动程序。一个驱动程序可以控制若干个设备,次设备号提供了一种区分它们的方法。在任何程序使用设备驱动程序之前,设备驱动程序应该向系统进行登记,以便系统在适当的时候调用。向系统增加一个驱动程序意味着要给它一个主设备号,这一过程应该在驱动程序的初始化过程中完成,调用如下函数:

int register_chrdev(major,*name,*fops)

      参数major是所求的主设备号,name是设备的名字,它们将在/proc/devices文件中出现,fops是一个指向跳转表的指针,利用这个跳转表完成对设备函数的调用。接下来觉得问题就是如何给程序一个它们可以请求你的设备驱动程序的名字。这个名字必须插入到/dev目录中,并与你的驱动程序的主设备号和次设备号相连。在文件系统上创建一个设备节点的命令是mknod,前提是你必须是超级用户。除了要创建的节点名外,该命令还带3个参数,例如mknod/dev/test c 98 0,其中/dev/test为设备节点的名字,c代表字符设备,98是主设备宝,0为次设备号。次设备号应该在0~255范围内。

       当从系统中卸载一个驱动程序模块时,应该释放主设备号。这一操作可以在cleanup_module中调用如下的函数完成:

int unregister_chrdev(major,*name)

      参数是要释放的主设备号和相应的设备名。内核对于这个名字和设备好的对应的名字进行比较,如果不同返回-ENINVAL,如果主设备号超出了允许范围或是并未分配给这个设备,内核一样返回-ENINVAL。

     

四、字符驱动程序模型

      考虑到字符设备一般采用中断的访问方式,所以该模型是选择中断访问外设的方式编写的。如果想用查询的方式,只需把申请和释放中断函数request_irq()、free_irq()及中断响应函数chr_interrupt()去掉就可以了。

      采用该模型编写字符设备驱动程序时可按以下步骤进行。

      1、收集到足够的外设硬件信息:如设备数据格式、中断号、采用串口还是并口,对它们初始化需要做哪些工作,读写设备时涉及到哪些寄存器。

      2、完成函数chr_module()和cleanup_module():前一函数包括检查外设是否存在、初始化该设备涉及到的硬件和数据结构、注册设备及向系统申请中断;后面的函数包括对硬件清零、释放内存、释放中断及注销设备。

     3、完成函数chr_open()和chr_release():前者包括部分的硬件和数据结构的初始化,后者包括释放不用的内存。

     4、完成函数chr_interrupt():修改程序开头定义的中断变量,填入外设的中断号。读取或写入外设的数据并进行简要的处理,读或写动作完成后唤醒睡眠的其他进程。

     5、完成函数read():处理中断函数中读取到的数据,并按照系统的默认格式赋给buffer数组。

     6、完成函数write():按照外设的数据格式处理buffer数组中的数据,准备在中断时写到外设上。

     最主要的步骤都已列出,把它们正确的完成以后,完整的字符设备驱动程序就容易完成了,当然还可以加入其他的函数如poll()和ioctl(),但这两个函数对字符设备作用不大。