初学Linux驱动程序的时候,可能对什么是字符设备驱动(char device)和杂项设备驱动(misc device)并不是很了解,更谈不上如何区分了。我自己当初在学习Linux字符设备驱动的时候,也并没有特地去了解其两者之间的区别,尤其是在两种驱动设备注册的时候,没有意识到其不同之处,导致后来在项目中出现了很严重的问题,但却迟迟到找不到解决方案。所以今天就趁这个机会,好好分析一下两者之间的区别,以便有出现在我类似问题的朋友,以后不会再犯同样的错误。
普通字符型设备
对于字符型设备,可能学习过Linux设备驱动的,都应该是比较了解得,并且我们在项目中大多要自己编写的驱动设备也都是字符类型的。在普通的字符型设备驱动注册的过程中,需要经过以下这几个步骤:
- 申请设备号
- 动态申请设备号(alloc_chrdev_region)
- 静态申请设备号(register_chrdev_region)
- 设备注册
-
- 为cdev分配空间(cdev_alloc)
- 初始化cdev(cdev_init)
- 将cdev添加进Kernel(cdev_add)
- 生成设备节点
- 创建class(class_create)
- 通过class,创建设备节点(device_create)
以上这些步骤其实在Linux2.6版本之前,都是直接使用register_chrdev函数一步到位,全部完成的。虽然使用register_chrdev在驱动程序注册的过程中变得简单了,但是却存在很大局限性,尤其用户自定性不高。因此目前的Linux内核,这两种方式都提供,但通常采用的方式,就是我上面写的那几个步骤。在设备注册这一步骤需要注意的是cdev_alloc和cdev_init这两个函数之间的区别。关于相同点和不同点,我还是直接上它们的代码进行分析:
struct cdev *cdev_alloc(void) //无参数
{
struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); //为cdev申请内存
if (p) {
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj, &ktype_cdev_dynamic); //这两步是初始化cdev,如将cde