Linux设备驱动模型-Kset
来源:互联网 发布:机械建模软件 编辑:程序博客网 时间:2024/04/30 09:57
前言
当多个kobject属于同一类的时候,为了方便管理,就引入了Kset。Kset可以认为是一组kobject的集合,是kobject的容器。
比如/sys/bus下就属于同一类kobject。
shell@test:/sys/bus $ lsclockeventsclocksourcecontainercoresightcpuevent_sourcehidi2ciiomdio_busmmcplatformscsisdioseriospiusbvirtioworkqueue
数据结构
linux内核使用struct kset结构体代表一个kset结构
struct kset {struct list_head list;spinlock_t list_lock;struct kobject kobj;const struct kset_uevent_ops *uevent_ops;};list: 用来将kset下的kobject使用链表管理。
list_lock: 对kset上的list访问操作时,使用spinlock进行互斥保护。
kobj: kset本身也是一个内核对象,所以需要嵌入kobject进行管理。
uevent_ops: kset的uevent操作函数集合。当其中的kobject对象的状态发生变化需要通知用户空间的时候,就需要调用uevent_ops中的函数。
struct kset_uevent_ops定义如下:
struct kset_uevent_ops {int (* const filter)(struct kset *kset, struct kobject *kobj);const char *(* const name)(struct kset *kset, struct kobject *kobj);int (* const uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env);};
kset操作
- kset_init(初始化一个kset对象)
/** * kset_init - initialize a kset for use * @k: kset */void kset_init(struct kset *k){kobject_init_internal(&k->kobj); //初始化kobjectINIT_LIST_HEAD(&k->list); //初始化链表spin_lock_init(&k->list_lock); //初始化自旋锁}
- kset_register(初始化然后添加kset)
/** * kset_register - initialize and add a kset. * @k: kset. */int kset_register(struct kset *k){int err;if (!k)return -EINVAL;kset_init(k); //初始化操作err = kobject_add_internal(&k->kobj); //将kset->kobject对象添加到sys下,此过程和添加kobject操作一样。if (err)return err;kobject_uevent(&k->kobj, KOBJ_ADD); //通过uevent机制通知用户空间return 0;}关于uevent机制,会在后面的uevent文章中详细说明,此处先跳过。
- kset_create(动态创建一个Kset)
tatic struct kset *kset_create(const char *name,const struct kset_uevent_ops *uevent_ops,struct kobject *parent_kobj){struct kset *kset;int retval;kset = kzalloc(sizeof(*kset), GFP_KERNEL);if (!kset)return NULL;retval = kobject_set_name(&kset->kobj, "%s", name); //设置name域if (retval) {kfree(kset);return NULL;}kset->uevent_ops = uevent_ops; //设置uevent_opskset->kobj.parent = parent_kobj; //设置parent/* * The kobject of this kset will have a type of kset_ktype and belong to * no kset itself. That way we can properly free it when it is * finished being used. */kset->kobj.ktype = &kset_ktype; //设置ktypekset->kobj.kset = NULL;return kset;}
- kset_create_and_add(kset_register和kset_create的结合体)
struct kset *kset_create_and_add(const char *name, const struct kset_uevent_ops *uevent_ops, struct kobject *parent_kobj){struct kset *kset;int error;kset = kset_create(name, uevent_ops, parent_kobj);if (!kset)return NULL;error = kset_register(kset);if (error) {kfree(kset);return NULL;}return kset;}
示例
本例看下/sys/module下节点的创建过程。
kernel/kernel/params.c------------------------------------static int __init param_sysfs_init(void){module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);if (!module_kset) {printk(KERN_WARNING "%s (%d): error creating kset\n",__FILE__, __LINE__);return -ENOMEM;}module_sysfs_initialized = 1;version_sysfs_builtin();param_sysfs_builtin();return 0;}可以看到通过kset_create_and_add创建一个名字为"module"的kset。表现在sys下就是在sys下存在一个module的目录。
root@sp9860g_1h10_3g:/sys/module # lsahci_xgeneaudio_smsgbcmdhdbinderblockbluetoothbrcm_lpmcfg80211configfscoresight_etm4xcpuidledm_bufiodm_moddm_veritydwc3dynamic_debug.....那module下的这些节点是什么时候创建的? 带着此问题继续看代码。
static void __init param_sysfs_builtin(void){const struct kernel_param *kp;unsigned int name_len;char modname[MODULE_NAME_LEN];for (kp = __start___param; kp < __stop___param; kp++) {char *dot;if (kp->perm == 0)continue;dot = strchr(kp->name, '.');if (!dot) {/* This happens for core_param() */strcpy(modname, "kernel");name_len = 0;} else {name_len = dot - kp->name + 1;strlcpy(modname, kp->name, name_len);}kernel_add_sysfs_param(modname, kp, name_len);}}对kernel中在.param段的模块参数,通过kernel_add_sysfs_param添加到sys中。而__start___param和__stop___param定义在链接脚本中。
/* Built-in module parameters. */\__param : AT(ADDR(__param) - LOAD_OFFSET) {\VMLINUX_SYMBOL(__start___param) = .;\*(__param)\VMLINUX_SYMBOL(__stop___param) = .;\}而这些模块参数,是通过module_param等相关函数设置的。
#define module_param(name, type, perm)\module_param_named(name, name, type, perm)
接着上面的分析,看kernel_add_sysfs_param此函数,在此函数中通过locate_module_kobject函数建立起与kset(module_kset)之间的联系。
static struct module_kobject * __init locate_module_kobject(const char *name){struct module_kobject *mk;struct kobject *kobj;int err;kobj = kset_find_obj(module_kset, name); //通过name域找下kobj是否存在,存在就返回,不存在创建新的if (kobj) {mk = to_module_kobject(kobj); } else {mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);BUG_ON(!mk);mk->mod = THIS_MODULE;mk->kobj.kset = module_kset;err = kobject_init_and_add(&mk->kobj, &module_ktype, NULL, //设置kset, ktype, 创建新的kobj "%s", name);#ifdef CONFIG_MODULESif (!err)err = sysfs_create_file(&mk->kobj, &module_uevent.attr); //创建kobj的属性,#endifif (err) {kobject_put(&mk->kobj);pr_crit("Adding module '%s' to sysfs failed (%d), the system may be unstable.\n",name, err);return NULL;}/* So that we hold reference in both cases. */kobject_get(&mk->kobj);}return mk;}
当用户通过insmod插入一个模块的时候,最后调用到init_module系统调用
SYSCALL_DEFINE3(init_module, void __user *, umod,unsigned long, len, const char __user *, uargs){int err;struct load_info info = { };err = may_init_module();if (err)return err;pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n", umod, len, uargs);err = copy_module_from_user(umod, len, &info);if (err)return err;return load_module(&info, uargs, 0);}下面是load_module的调用流程,只关心跟本节相关的。
load_module ->mod_sysfs_setup ->module_param_sysfs_setup ->add_sysfs_param new->grp.name = "parameters"; new->grp.attrs = attrs; new->attrs[num].mattr.show = param_attr_show; new->attrs[num].mattr.store = param_attr_store;
最终会在/sys/module下的任何一个模块,都会有一个名字为"parameters"的目录。比如/sys/module/printk
root@test:/sys/module/printk # lsparametersuevent在parameters下的模块参数有:
root@test:/sys/module/printk/parameters # lsalways_kmsg_dumpconsole_suspendcpuidignore_logleveltime这些属性都是在printk中通过
module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);相同此种方法创建的。
0 0
- Linux设备驱动模型-Kset
- Linux设备驱动模型三 kset
- Linux设备驱动模型三 kset
- Linux 设备模型 --- Kset
- LINUX设备驱动之设备模型二--kset
- LINUX设备驱动之设备模型二--kset
- LINUX设备驱动之设备模型二--kset
- LINUX设备驱动之设备模型二--kset
- linux设备驱动模型一三基础结构之Kset
- linux设备驱动模型之 kset原理与实例分析
- linux ------ 设备驱动模型之一(sysfs, koject, kset)
- linux设备驱动模型一三基础结构之Kset
- linux设备驱动模型之 kset原理与实例分析
- linux总线设备驱动模型之Kobject&Kset
- Linux Kernel设备驱动模型之struct kset
- linux设备驱动模型之Kobject、kobj_type、kset
- linux设备驱动模型(kobject与kset)
- linux设备驱动之kset
- H5 缓存机制浅析 移动端 Web 加载性能优化
- 安卓基础概述
- 电脑出题
- 机器学习算法汇总:人工神经网络、深度学习及其它
- 微信小程序开发教程
- Linux设备驱动模型-Kset
- SDWebImage深度使用
- Linux中的for循环
- VS2013下 关于解决检测到 Mac 文件格式: 请将源文件转换为 DOS 格式或 UNIX 
- servlet3.1规范: 第5章 响应(Response)
- 加密密码涉及到将小写用户名改为大写
- Golang 基础 HTTP服务器
- 数据结构——dll的创建和使用
- 考虑这个简单的函数