字符設(shè)備驅(qū)動模型淺析
復(fù)制代碼
接著又調(diào)用了函數(shù)cdev_add(),這個函數(shù)又調(diào)用了kobj_map()函數(shù),其作用就是分配一個struct probe結(jié)構(gòu)體,填充該結(jié)構(gòu)體中的變量并將其加入到全局的cdev_map中,說白了,就是分個一畝三分田給該字符設(shè)備驅(qū)動,并做好標(biāo)記,放到主設(shè)備號對應(yīng)的地方,等主人下次來找的時候能找到(使用kobj_lookup()函數(shù),后面會講到)。該函數(shù)是這樣的,int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
struct module *module, kobj_probe_t *probe,
int (*lock)(dev_t, void *), void *data)
{
unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
unsigned index = MAJOR(dev);
unsigned i;
struct probe *p;
if (n > 255)
n = 255;
/*分配了一畝三分田*/
p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL);
if (p == NULL)
return -ENOMEM;
/*填充些私有的東西*/
for (i = 0; i owner = module;
p->get = probe; /*是exact_match ()函數(shù),獲取cdev結(jié)構(gòu)體的kobject指針*/
p->lock = lock; /*是exact_lock()函數(shù),增加引用*/
p->dev = dev;
p->range = range;
p->data = data; /* cdev保存到p->data中*/
}
mutex_lock(domain->lock);
/*將這一畝三分田加到主設(shè)備號對應(yīng)的位置上去*/
for (i = 0, p -= n; i probes[index % 255];
while (*s (*s)->range next;
p->next = *s;
*s = p;
}
mutex_unlock(domain->lock);
return 0;
}
復(fù)制代碼接下來有class_create()函數(shù)和class_device_create()函數(shù),前者生成一個名字為testchar的class,后者作用就是在/dev目錄下生成設(shè)備節(jié)點,當(dāng)然,需要uevent和UDEVD的支持,具體可見鄙人博客上的文章《Linux設(shè)備模型淺析之uevent篇》。
順帶說下register_chrdev()函數(shù),其也是注冊字符設(shè)備驅(qū)動,只不過是封裝好的,包含了所有前面講的注冊步驟——分配一個設(shè)備號,由一個主設(shè)備號和255個次設(shè)備號組成。如下,int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
{
struct char_device_struct *cd;
struct cdev *cdev;
char *s;
int err = -ENOMEM;
cd = __register_chrdev_region(major, 0, 256, name);
if (IS_ERR(cd))
return PTR_ERR(cd);
cdev = cdev_alloc(); /*這個有點不一樣,動態(tài)分配的,不是調(diào)用者提供*/
if (!cdev)
goto out2;
cdev->owner = fops->owner;
cdev->ops = fops;
kobject_set_name( %s, name);
for (s = strchr(kobject_name( s; s = strchr(s, '/'))
*s = '!';
err = cdev_add(cdev, MKDEV(cd->major, 0), 256);
if (err)
goto out;
cd->cdev = cdev;
return major ? 0 : cd->major;
out:
kobject_put(
out2:
kfree(__unregister_chrdev_region(cd->major, 0, 256));
return err;
}
評論