Linux设备驱动模型-Kset
前言
shell@test:/sys/bus $ ls
clockevents
clocksource
container
coresight
cpu
event_source
hid
i2c
iio
mdio_bus
mmc
platform
scsi
sdio
serio
spi
usb
virtio
workqueue
数据结构
struct kset {struct list_head list;spinlock_t list_lock;struct kobject kobj;const struct kset_uevent_ops *uevent_ops;
};
list: 用来将kset下的kobject使用链表管理。
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;
}
示例
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 # ls
ahci_xgene
audio_smsg
bcmdhd
binder
block
bluetooth
brcm_lpm
cfg80211
configfs
coresight_etm4x
cpuidle
dm_bufio
dm_mod
dm_verity
dwc3
dynamic_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_paramnew->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 # ls
parameters
uevent
在parameters下的模块参数有:
root@test:/sys/module/printk/parameters # ls
always_kmsg_dump
console_suspend
cpuid
ignore_loglevel
time
这些属性都是在printk中通过
module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);
相同此种方法创建的。
Linux设备驱动模型-Kset相关推荐
- Linux中kobject的作用,Linux设备驱动模型-- 数据结构Kset/KObject
前言 Kset和kobject是Linux设备驱动模型中的核心数据结构,其主要作用是将系统中的设备抽象出来,以树状结构组织,方便系统统一管理. 而这个统一管理的地方,就是sysfs,先放一张示例图,阐 ...
- Linux设备驱动模型三 kset
Linux设备驱动模型三 kset 1 kset数据结构 kset的定义在前文已有描述,我们再回顾一下: [cpp] view plain copy struct kset { /*与子kobject ...
- linux 统一设备模型 pci,Linux设备驱动模型摘抄
Linux设备驱动模型摘抄Linux设备驱动模型摘抄Linux设备驱动模型摘抄Linux设备驱动模型摘抄Linux设备驱动模型摘抄 Linux设备驱动模型摘抄(1) Linux统一设备模型 简介 Li ...
- Linux设备驱动模型1——简介和底层架构
以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 一.linux设备驱动模型简介 1.什么是设备驱动模型? (1)类class.总线bus.设备device.驱动d ...
- Linux设备驱动模型之platform(平台)总线详解
/********************************************************/ 内核版本:2.6.35.7 运行平台:三星s5pv210 /*********** ...
- Linux设备驱动模型二 kobject
Linux设备驱动模型二 kobject 1 kobject 1.1 kobject数据结构 kobject是sysfs文件系统的基础数据结构,它定义在include/linux/kobjec.h中 ...
- Linux设备驱动模型一 sysfs
Linux设备驱动模型一 sysfs 1 Linux设备模型 Linux 2.5的内核引入了一种新的设备模型,目的是对计算机上的所有设备进行统一的管理. 它包含以下基础结构: 类型 说明 设备Devi ...
- 五.linux设备驱动模型
站在设备驱动这个角度分析,设备驱动模型是如何构建出来,起到什么作用,认识它并在写驱动的时候去利用设备驱动模型 目录 一.linux 设备驱动模型简介 1.1. 什么是设备驱动模型 1.2. 为什么需要 ...
- 整理--linux设备驱动模型
知识整理–linux设备驱动模型 以kobject为底层,组织类class.总线bus.设备device.驱动driver等高级数据结构,同时实现对象引用计数.维护对象链表.对象上锁.对用户空间的表示 ...
- LINUX设备驱动模型分析之三 驱动(DRIVER)接口分析
上一章我们分析了bus-driver-device模型中bus接口部分,本章我们将分析driver接口,在bus-driver-device模型中,driver接口是依附于bus上,而不像device ...
最新文章
- 比特币核心(BCE)或许并没有你想象的强大
- .Net Telerik Web UI 安装和使用入门
- Hadoop学习笔记—1.基本介绍与环境配置
- solver.prototxt参数说明(二)
- mysql事务,START TRANSACTION, COMMIT和ROLLBACK,SET AUTOCOMMIT语法
- Java认证授权框架Spring Security介绍
- Struts 2的OGNL表达式
- WPF之无法触发KeyDown或者KeyUp键盘事件
- Nodejs正则表达式函数之match、test、exec、search、split、replace使用详解
- jenkins java常用插件下载,Jenkins简单介绍以及插件入门
- 【Low版】HAUT - OJ - Contest1035 - 2017届新生周赛(六)题解
- 厦门大学考研:必知20大时间节点
- GeekTool使用备忘
- java实现微信H5支付和回调的Demo源码
- 【转】巧舟的逆转裁判开发手记~
- rtspplayer播放器实现
- matlab patch 六面体,[MATLAB数学相关] 求正六面体的细分格式
- python基础 日常总结——列表(二)
- linux系统下操作nandflash指令,Linux驱动之Nand Flash原理及硬件操作
- 条件求和:SUMIF、SUMIFS函数
热门文章
- 当前网络存在的安全问题
- Linux驱动的platform机制
- IIS连接oralce数据提示“System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本”...
- java byte与char互转原理
- 游戏娱乐计算机配置方案,计算机配置方案.doc
- Java NIO 详解(二)
- 开发环境、生产环境、测试环境的基本理解和区别
- backbond Model实现
- 给Eclipse中hibernate.cfg.xml配置文件加提示
- LinkedHashMap与HashMap的使用比较