- static way
- declare
- embedded in your device structure statically
struct dummy_device {
struct cdev cdev;
}; - initialize
- use cdev_init() function to initialize the cdev structure
struct dummy_device dev;
...
cdev_init(&dev.cdev, &dummy_fops); - remove
- call cdev_del()
- dynamic way
- declare
- memory of cdev structure is allocated dynamically
struct dummy_device {
struct cdev *cdev;
};
...
struct dymmy_device dev;
dev->cdev = cdev_alloc(); - initialize
- dev->cdev.fops = &dummy_fops;
- remove
- call cdev_del()
- You don't need to call kfree() to free memory. Kernel releases the memory automatically. (talk this later)
If you use dynamic way to create a cdev structure, you should better not use cdev_init() to initialize the structure.
Let's check source code.
void cdev_init(struct cdev *cdev,
const struct file_operations *fops)
{
memset(cdev, 0, sizeof *cdev);
INIT_LIST_HEAD(&cdev->list);
kobject_init(&cdev->kobj, &ktype_cdev_default);
cdev->ops = fops;
}
struct cdev *cdev_alloc(void)
{
/* cdev is allocated here! */
struct cdev *p = kzalloc(sizeof(struct cdev),
GFP_KERNEL);
if (p) {
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj, &ktype_cdev_dynamic);
}
return p;
}
If you use dynamic way to create the cdev structure, ktype_cdev_dynamic() is used to release cdev kobject.
If you use cdev_init() to initialize cdev structure that is created in dynamic way, release function of kobject is replaced with ktype_cdev_default().
In this case, after you invoke cdev_del() to remove a cdev device from kernel, this causes a memory leak.
You need to free memory manually and it is not recommended.
static void cdev_default_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);
cdev_purge(p);
}
static void cdev_dynamic_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);
cdev_purge(p);
kfree(p); /* cdev is freed here! */
}
static struct kobj_type ktype_cdev_default = {
.release = cdev_default_release,
};
static struct kobj_type ktype_cdev_dynamic = {
.release = cdev_dynamic_release,
};
沒有留言:
張貼留言