天天看点

《LINUX设备驱动程序》学习札记(二)

总结章节:第三节 字符设备驱动

这一章主要是讲一些字符设备驱动程序的相关知识。在进行字符设备驱动程序学习之前,我们必须得弄明白一个问题:驱动程序时给谁用的。

很多驱动程序的初学者,按照一般编程语言(c,java等等)编写应用程序的经验,函数就是用来调用的。这种调用关系,在应用空间来看,限制不是很明显。很多初学者都会误认为,在驱动程序中写的函数是为了以后应用程序来调用,比如:在驱动中程序中实现了switch()函数的功能,按照应用程序的观念,在应用程序中应该可以调用switch()函数,从而来实现某种功能。这种错误的思维在从用户空间应用程序程序员到驱动程序程序员的转变过程中,经常会遇到这种问题。这其实是对驱动程序的本质属性没有弄透彻。驱动程序,就是内核的一部分,驱动程序的代码是内核代码的一部分。应用程序不能直接利用驱动程序来达到访问硬件的目的,我们应该明白,应用程序是通过访问/dev/下的设备文件,来间接的访问硬件,驱动程序通过系统调用来实现将信息传递给/dev/下的设备文件。无论驱动程序中定义了什么函数,应用空间都不能使用,哪怕是函数形态一样,如果可以访问的话,那就危险了。驱动程序中的函数永远都是提供给系统内核使用的,由系统来自动调用,不需要应用程序干预。

搞清楚上面的问题之后,来看看字符设备驱动的一些重要的概念和数据结构。

1.    设备号

在linux 2.6内核中,用32位的dev_t类型的数据来表示,其中12位用来表示主设备号,其余20位用来表示次设备号。主设备号是用来表示设备所对应的驱动程序的,也就是说,如果设备的主设备号相同,那么这些设备的驱动程序是同一个。次设备号是给内核使用的,用来确定设备文件所指向的设备。尽管主设备号和次设备号的位数都固定了,但是,我们不应做出任何假设,如果我们需要从一个dev_t  dev(以后的使用中,设备号都是指dev_t类型的设备号)中得到主设备号和次设备号,应该使用下面的宏:

                       major(dev_t dev);

                       minor(dev_t dev);

如果我们想用主设备号和此设备号来得到dev_t类型的设备号,应该使

2.    分配设备号

通常情况下,我们应该尽量使用动态分配设备号的方式。

       int  alloc_chrdev_region(dev_t  *dev,  unsigned int firstminor,  unsigned count,  char  *name);

这个函数将把申请范围内身亲到的第一个设备号传给*dev.

当然,在已经知道设备号的前提下,使用

      int  register_chrdev_region(dev_t  first,  unsigned int count,  char  *name)

其中   first是申请设备号范围内的其实设备号。first中的minor部分常常设为0.

但是,不论使用了哪种方式来分配设备号,我们都需要使用

     void  unregister_chrdev_region(dev_t  first, unsigner int count).

另外,由于动态分配设备号所分配的设备号不是确定的,那么对于创建设备文件就比较麻烦了,但是我们可以使用脚本来自动创建,关于自动创建设备文件的脚本的理解详见我的博客中的关于awk的解释。

3.    重要的数据结构  file_operations    file    inode

 关于这些数据结构的内容,我就不多说了,只想说明一些关键性的问题,file_operations数据结构定义了一些操作,一个设备文件只有一个 inode,但是可以有多个file结构。file是在打开设备文件后由内核自动创建的。file结构用来表示一个打开的文件,而inode用来表示一个文件了。驱动程序的编写实质性的工作就是对这些结数据结构进行填充,对相关数据结构中的函数进行实现

4.设备注册

设备注册的函数就不用讲了。按照函数语法使用就可以了。

版权申明:

转载文章请注明原文出处http://blog.csdn.net/feiyinzilgd/archive/2010/12/30/6108417.aspx

并请联系谭海燕本人或者前往谭海燕个人主页留言