首页 理论教育字符设备驱动框架在ARM嵌入式系统中的应用

字符设备驱动框架在ARM嵌入式系统中的应用

【摘要】:上面介绍了字符设备驱动程序的重要的数据结构,那么如何设计一个字符设备驱动程序的数据结构?字符设备驱动程序的初始化流程一般可以用如下的过程来表示:定义相关的设备文件结构体[如file_operation()中的相关成员函数的定义]。向内核申请主设备号。内核提供了三个函数来注册一组字符设备编号,这三个函数分别是:alloc_chrdev_region()、register_chrdev_region()和register_chrdev()。所以在一般的字符设备驱动程序中,不会看到对cdev的操作。这里举出字符设备驱动程序的常见的两种编程架构。

上面介绍了字符设备驱动程序的重要的数据结构,那么如何设计一个字符设备驱动程序的数据结构?接下来介绍编写驱动程序的步骤和结构体之间的层次关系。

字符设备驱动程序的初始化流程一般可以用如下的过程来表示:

(1)定义相关的设备文件结构体[如file_operation()中的相关成员函数的定义]。

(2)向内核申请主设备号(建议采用动态方式)。

(3)申请成功后,通过调用MAJOR()函数获取主设备号。

(4)初始化cdev的结构体,可以通过调用cdev_init()函数实现。

(5)通过调用cdev_add()函数注册cdev到内核。

(6)注册设备模块,主要使用module_init()函数和module_exit()函数。

编写一个字符设备的驱动程序,首先要注册一个设备号。内核提供了三个函数来注册一组字符设备编号,这三个函数分别是:alloc_chrdev_region()、register_chrdev_region()和register_chrdev()。下面具体分析各个函数的参数原型和意义。

register_chrdev_region()函数用于向内核申请分配已知可用的设备号(次设备号通常为0)范围。下面是该函数原型:(www.chuimin.cn)

int register_chrdev_region(dev_t from,unsigned count,const char∗name)。

参数from是要分配的设备号的dev_t类型数据,表示了要分配的设备编号的起始值,参数count表示了允许分配设备编号的范围。

register_chrdev()是一个老版本内核的设备号分配函数,不过新内核对其还是兼容的。Register_chrdev()兼容了动态和静态两种分配方式。Register_chrdev()不仅分配了设备号,同时也注册了设备。这是register_chrdev()与前两个函数的最大区别。也就是说,如果使用alloc_chrdev_region()或register_chrdev_region()分配设备号,还需要对cdev结构体初始化。而register_chrdev()则把对cdev结构体的操作封装在了函数的内部。所以在一般的字符设备驱动程序中,不会看到对cdev的操作。

与注册分配字符设备编号的方法类似,内核提供了两个注销字符设备编号范围的函数unregister_chrdev_region()和unregister_chrdev()。这两个函数实际上都调用了__unregister_chrdev_region()函数,原理是一样的。

Register_chrdev()函数封装了cdev结构的操作,而alloc_chrdev_region()或register_chrdev_region()只提供了设备号的注册,并未真正的初始化一个设备,只有cdev这个表示设备的结构体初始化了,才可以说设备初始化了。

这里举出字符设备驱动程序的常见的两种编程架构

架构一:

这两个结构中,前一个应用register_chrdev函数封装了cdev,后面可以直接定义file_operations结构体提供系统调用接口。后一种架构用alloc_chrdev_region注册设备号,然后用cdev_init初始化了一个设备,接着用cdev_add添加了该设备。两种架构在模块卸载函数中,分别用相应的卸载函数实现。

当file_operations结构与设备关联在一起后,就可以在驱动的架构中补全file_operations的内容,实现一个完整的驱动架构,比如: