以LED驱动为例,将驱动编写为模块!
一、旧字符驱动组成
1、实现设备的具体操作函数,初始化操作函数结构体struct file_operations变量。
2、驱动入口函数,也就是模块加载函数xxx_init。
3、在模块加载函数中,以设备号、设备操作函数结构体变量、设备名为基础,使用register_chrdev函数注册字符设备驱动。
4、驱动出口函数,也就是模块卸载函数xxx_exit。
5、在模块卸载函数中,以设备号、设备名为基础,使用unregister_chrdev函数卸载字符设备驱动。
6、LICENSE(不可省略)和作者信息(可省略)。
MODULE_LICENSE("GPL");
MODULE_AUTHOR("author");
二、新字符设备驱动组成
1、硬件设备对应的结构体,包含了设备号、字符设备驱动、类、设备信息等。
2、实例化硬件设备结构体,也就是实例化LED设备结构体。
struct newchrled_dev newchrled; /* led 设备 */
3、字符设备驱动具体操作函数,以及字符设备驱动函数结构体初始化。
4、字符设备驱动入口函数。
static int __init led_init(void) {...}
5、在入口函数中,注册字符设备驱动。 包括创建设备号( register_chrdev_region或alloc_chrdev_region)、初始化并添加cdev字符设备驱动结构体到linux系统(cdev_init、cdev_add)(使用字符设备驱动具体操作函数结构体变量)、创建类和设备(class_create、device_create)。
6、字符设备驱动出口函数。
7、在出口函数内,注销字符设备驱动。包括删除cdev字符设备驱动结构体(cdev_del)、注销设备号(unregister_chrdev_region)、删除创建的设备和类(device_destroy、 class_destroy)。
三、主要区别
1、设备号获取方式不同
旧字符设备驱动: 自行指定主设备号,
新字符设备驱动: 自动分配, 或者自行制定主设备、次设备号。
2、字符设备注册方式不同
旧字符设备驱动: 通过register_chrdev + 主设备号 + file_operations结构体 直接注册,
新字符设备驱动: cdev 结构体表示字符设备,cdev_init 函数对其进行初始化,然后使用 cdev_add 函数向 Linux 系统添加这个字符设备。
3、设备结点文件生成方式不同
旧字符设备驱动: 手动使用命令生成,
新字符设备驱动: 通过配置自动生成。