kobject在字符设备中的使用
作者:linuxer 发布于:2014-12-4 18:14
一、前言
关于kobject的基本概念的描述请参考Linux设备模型(2)_Kobject中的描述。本文主要以字符设备为例,描述内核中使用kobject的一个场景,以便加深对kobject这个内核神器的理解。
二、定义
内核中用struct cdev来表示一个字符设备,具体数据结构定义如下:
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
在linux kernel中大量使用了面向对象的思想(虽然c语言不是一种面向对象的语言,但是,仍然可以体现一些面向对象的思想)。对于c++而言,有基类和派生类,派生类可以继承基类的一些接口和属性。对于c而言,我们将kobject嵌入到其他数据结构中的方式来实现继承。
三、初始化
1、driver动态分配struct cdev的场景
register_chrdev接口函数是2.4 kernel时代的API,到了2.6时代,为了兼容之前的旧的driver,内核仍然提供了这个接口函数,但是底层已经是使用新的字符设备的接口函数了,具体如下:
int __register_chrdev(……)
{
……cdev = cdev_alloc();-------------------动态分配struct cdev
……
kobject_set_name(&cdev->kobj, "%s", name); -------设定kobject的名字err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);---将字符设备加入系统
……
}
动态分配struct cdev的过程如下:
struct cdev *cdev_alloc(void)
{
struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);--------(1)
if (p) {
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj, &ktype_cdev_dynamic);-------------(2)
}
return p;
}
(1)分配了struct cdev,也就分配了kobject的memory,他们是共存亡的。
(2)初始化kobject,注意:这里的ktype_cdev_dynamic非常关键,和消耗cdev这个对象(也就是销毁kobject这个对象相关),可以参考第四章的描述。
2、driver静态定义struct cdev的场景
有的时候,我们的字符设备的cdev是静态定义的,例如:
static struct cdev xxx_cdev;
当然,也有可能cdev这个数据结构是嵌入到你自己定义的数据结构struct xxx_cdev中,然后静态定义一个struct xxx_cdev的变量。当然,它们本质上是一样的。对于这样静态定义的cdev,我们使用cdev_init来初始化。我们来看一看cdev_init中如何初始化kobject:
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);-----------(1)
cdev->ops = fops;
}
和cdev_alloc一样,调用kobject_init初始化内嵌的kobject,不过ktype是不一样的,这里是ktype_cdev_default。
三、将kobject加入系统
通过cdev_add可以将cdev注册到系统中:
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
……kobject_get(p->kobj.parent);
return 0;
}
期待的kobject_add没有出现,只有增加了cdev中kobject的parent的引用计数,当然,如果在你的driver中不设定parent,其实这个调用也是没有意义的。
四、注销
对于静态定义的cdev(因此kobject也是静态定义),无所谓销毁,因此该kobject的ktype的release函数不需要释放内存,大家可以去看看cdev_default_release函数。对于动态分配的cdev(因此kobject也是动态分配),其ktype是:
static struct kobj_type ktype_cdev_dynamic = {
.release = cdev_dynamic_release,
};
在函数中会释放内存,具体如下:
static void cdev_dynamic_release(struct kobject *kobj)
{
struct cdev *p = container_of(kobj, struct cdev, kobj);----找到kobject对应的cdev对象
struct kobject *parent = kobj->parent;cdev_purge(p);
kfree(p);--------------释放内存
kobject_put(parent);
}

评论:
2014-12-09 09:45
前面你和wowo已经论证过cdev与设备模型无关,那么你是怎么理解cdev中出现的kobject? 没看出来它在这里的作用。
2014-12-09 12:14
对于cdev这个场景,kobject主要是应用两点:
1、reference count。
2、ktype中的release函数
基本上可以这么认为,cdev中的kobject没有完全发挥其功能,假设其全部功能有10条,实际只用了2条。是不是很浪费?当然是很浪费了,如果有可能,最好定义一个基类,只包括上面的那两点功能,kobject派生于此基类,cdev也是派生于此基类。当然,是否定义这样的基类应该是内核中的应用场景相关,如果有大量类似cdev这样的场景,我们相信内核人员有可能定义这样的基类
功能
最新评论
- wangjing
写得太好了 - wangjing
写得太好了! - DRAM
圖面都沒辦法顯示出來好像掛點了。 - Simbr
bus至少是不是还有个subsystem? - troy
@testtest:只要ldrex-modify-strex... - gh
Linux 内核在 sparse 内存模型基础上实现了vme...
文章分类
随机文章
文章存档
- 2025年4月(5)
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2014-12-09 12:26
我觉得这段解释有必要加入到正文中去,说起来,bbs怎么没有编辑功能呢?