[linux device driver] Chapter 03:字符设备注册学习
2015-02-21 21:18
567 查看
从函数scullc_init中学习register_chrdev_region,进而进入到__register_chrdev_region,主要还是研究__register_chrdev_region这个函数。
__register_chrdev_region:
从上面可以看出,__register_chrdev_region完成的工作主要有三个步骤:
1. 分配出一个char_device_struct 结构,使用对应的入参赋值。
2.从chrdevs上找到对应的major号的chrdevs[major],然后从这个散列表中一级一级往下查找对应的minor号,最近将已经分配好的char_device_struct挂载到chrdevs全局变量中。
值得注意的是__register_chrdev_region的这个部分:
这段代码的主要作用是从chrdevs[i]
chrdevs是一个255个char_device_struct的数组指针:
它是一个散列表,取得i项chardevs后,函数不停的判断(*cp)->major是否大于或者是等于且baseminor也大于等于baseminor,这样最后在正常情况下会因为*cp=null而退出,从而cd->next = null,而*cp=cd,将cd挂载到*cd上,其实也就是chrdevs下的某一项。相对来说介绍详细的文章是这个:http://blog.csdn.net/yel617/article/details/5627505
__register_chrdev_region:
static struct char_device_struct * __register_chrdev_region(unsigned int major, unsigned int baseminor, int minorct, const char *name) { struct char_device_struct *cd, **cp; int ret = 0; int i; cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL); if (cd == NULL) return ERR_PTR(-ENOMEM); memset(cd, 0, sizeof(struct char_device_struct)); write_lock_irq(&chrdevs_lock); /* temporary */ //如果major=0,那么就是动态分配,函数从chrdevs中找到未分配的数组元素分配。 if (major == 0) { for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) { if (chrdevs[i] == NULL) break; } if (i == 0) { ret = -EBUSY; goto out; } major = i; ret = major; } cd->major = major; cd->baseminor = baseminor; cd->minorct = minorct; cd->name = name; i = major_to_index(major); //这个循环的作用是从major对应的散列表中找到一项*cp = null,这样用于分配。 for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) if ((*cp)->major > major || ((*cp)->major == major && (*cp)->baseminor >= baseminor)) break; if (*cp && (*cp)->major == major && (*cp)->baseminor < baseminor + minorct) { ret = -EBUSY; goto out; } cd->next = *cp;//此时*cp = null *cp = cd; //把已经赋值好的cd挂到cp上,其实就是chrdevs[i]下对应的某个项 write_unlock_irq(&chrdevs_lock); return cd; out: write_unlock_irq(&chrdevs_lock); kfree(cd); return ERR_PTR(ret); }
从上面可以看出,__register_chrdev_region完成的工作主要有三个步骤:
1. 分配出一个char_device_struct 结构,使用对应的入参赋值。
2.从chrdevs上找到对应的major号的chrdevs[major],然后从这个散列表中一级一级往下查找对应的minor号,最近将已经分配好的char_device_struct挂载到chrdevs全局变量中。
值得注意的是__register_chrdev_region的这个部分:
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next) if ((*cp)->major > major || ((*cp)->major == major && (*cp)->baseminor >= baseminor)) break; if (*cp && (*cp)->major == major && (*cp)->baseminor < baseminor + minorct) { ret = -EBUSY; goto out; } cd->next = *cp; *cp = cd;
这段代码的主要作用是从chrdevs[i]
chrdevs是一个255个char_device_struct的数组指针:
static struct char_device_struct { struct char_device_struct *next; unsigned int major; unsigned int baseminor; int minorct; const char *name; struct file_operations *fops; struct cdev *cdev; /* will die */ } *chrdevs[MAX_PROBE_HASH];
它是一个散列表,取得i项chardevs后,函数不停的判断(*cp)->major是否大于或者是等于且baseminor也大于等于baseminor,这样最后在正常情况下会因为*cp=null而退出,从而cd->next = null,而*cp=cd,将cd挂载到*cd上,其实也就是chrdevs下的某一项。相对来说介绍详细的文章是这个:http://blog.csdn.net/yel617/article/details/5627505
相关文章推荐
- [linux device driver] Chapter 03:从scull_load学习小括号,中括号,和大括号的区别
- Linux设备驱动程序学习(1)-字符设备驱动程序
- Linux设备驱动程序第三版学习(7)- 高级字符驱动程序操作(续2)- poll/select
- Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]
- 国嵌--linux字符设备驱动学习之memdev设备
- Linux设备驱动程式学习(5)-高级字符驱动程式操作[(2)阻塞型I/O和休眠]
- Linux设备驱动程序学习(1)-字符设备驱动程序
- Linux设备驱动程序第三版学习(5)- 高级字符驱动程序操作 - ioctl .
- 基于mini6410的linux驱动学习总结(二 字符设备与块设备的区别)
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- linux字符设备驱动程序学习实验记录
- Linux设备驱动程序第三版学习(2)-字符设备驱动程序源码分析(续)
- Linux设备驱动程序学习(4) -高级字符驱动程序操作[(1)ioctl and llseek]
- 基于mini6410的linux驱动学习总结(四 设计字符设备驱动程序)
- Linux设备驱动程序学习(1)-字符设备驱动程序
- Linux设备驱动程序第三版学习(6)- 高级字符驱动程序操作(续1) - 进程休眠
- linux驱动学习(四) linux字符设备驱动 cdev
- linux字符设备驱动学习笔记2
- Linux设备驱动程式学习(6)-高级字符驱动程式操作[(3)设备文档的访问控制]
- 基于mini6410的linux驱动学习总结(五 字符设备驱动程序实例分析(虚拟设备驱动))