register_chrdev_region(dev_tfirst,unsigned int count,char *name) First :要分配的设备编号范围的初始值(次设备号常设为0); Count:连续编号范围. Name:编号相关联的设备名称. (/proc/devices); 动态分配: Int alloc_chrdev_region(dev_t *dev,unsigned int firstminor,unsignedint count,char *name); Firstminor : 通常为0; *dev:存放返回的设备号; 释放: Void unregist_chrdev_region(dev_t first,unsigned int count); 调用Documentation/devices.txt中能够找到已分配的设备号.
所以下面先来看一下__register_chrdev_region() 函数的实现代码。
__register_chrdev_region() static struct char_device_struct *__register_chrdev_region(unsigned int major, unsigned intbaseminor, int minorct, const char *name){ struct char_device_struct *cd,**cp; int ret = 0; int i; cd = kzalloc(sizeof(structchar_device_struct), GFP_KERNEL); if (cd == NULL) returnERR_PTR(-ENOMEM); mutex_lock(&chrdevs_lock); if (major == 0) { for (i =ARRAY_SIZE(chrdevs)-1; i > 0; i--) if(chrdevs[i] == NULL) break; if (i == 0){ ret =-EBUSY; gotoout; } major =i; ret =major; } cd->major =major; cd->baseminor =baseminor; cd->minorct =minorct; strncpy(cd->name,name, 64); i =major_to_index(major); for (cp =&chrdevs[i]; *cp; cp =&(*cp)->next) if((*cp)->major > major || ((*cp)->major == major&& (((*cp)->baseminor >= baseminor) ||((*cp)->baseminor + (*cp)->minorct> baseminor)) )) break; if (*cp&& (*cp)->major ==major) { int old_min= (*cp)->baseminor; int old_max= (*cp)->baseminor + (*cp)->minorct -1; int new_min= baseminor; int new_max= baseminor + minorct - 1;
intregister_chrdev_region(dev_t from, unsigned count, const char*name) { struct char_device_struct*cd; dev_t to = from + count; dev_t n, next;
for (n = from; n< to; n = next) { next =MKDEV(MAJOR(n)+1, 0); if (next> to) next =to; cd =__register_chrdev_region(MAJOR(n), MINOR(n), next - n, name); if(IS_ERR(cd)) gotofail; } return 0; fail: to = n; for (n = from; n< to; n = next) { next =MKDEV(MAJOR(n)+1, 0); kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next -n)); } return PTR_ERR(cd); }
cd =__register_chrdev_region(major, 0, 256, name); if (IS_ERR(cd)) returnPTR_ERR(cd);
cdev = cdev_alloc(); if (!cdev) gotoout2;
cdev->owner =fops->owner; cdev->ops =fops; kobject_set_name(&cdev->kobj, "%s",name); for (s =strchr(kobject_name(&cdev->kobj),'/');s; s = strchr(s, '/')) *s ='!';
err = cdev_add(cdev,MKDEV(cd->major, 0), 256); if (err) gotoout;
static struct char_device_struct *__unregister_chrdev_region(unsigned major, unsigned baseminor, intminorct) { struct char_device_struct *cd= NULL, **cp; int i =major_to_index(major);
mutex_lock(&chrdevs_lock); for (cp =&chrdevs[i]; *cp; cp =&(*cp)->next) if((*cp)->major == major&& (*cp)->baseminor == baseminor&& (*cp)->minorct == minorct) break; if (*cp) { cd =*cp; *cp =cd->next; } mutex_unlock(&chrdevs_lock); return cd; }
void unregister_chrdev_region(dev_t from, unsigned count) { dev_t to = from + count; dev_t n, next;
for (n = from; n< to; n = next) { next =MKDEV(MAJOR(n)+1, 0); if (next> to) next =to; kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next -n)); } }
void unregister_chrdev(unsigned int major, const char *name) { struct char_device_struct*cd; cd =__unregister_chrdev_region(major, 0, 256); if (cd&& cd->cdev) cdev_del(cd->cdev); kfree(cd);