linux设备驱动模型之 kset原理与实例分析
1、 Kset
???????kset是具有相同類型的kobject的集合,在sysfs中體現(xiàn)成一個(gè)目錄,在內(nèi)核中用kset數(shù)據(jù)結(jié)構(gòu)表示,定義為:
struct kset {
struct list_head list; //連接該kset中所有kobject的鏈表頭
spinlock_t list_lock;
struct kobject kobj; //內(nèi)嵌的kobject
struct kset_uevent_ops *uevent_ops; //處理熱插拔事件的操作集合
}
2、 Kset操作
?????? 1)int kset_register(struct kset *kset)
?????? 在內(nèi)核中注冊一個(gè)kset
?????? 2)void kset_unregister(struct kset *kset)
?????? 從內(nèi)核中注銷一個(gè)kset
3、 熱插拔事件
?????? 在Linux系統(tǒng)中,當(dāng)系統(tǒng)配置發(fā)生變化時(shí),如:添加kset到系統(tǒng);移動(dòng)kobject, 一個(gè)通知會(huì)從內(nèi)核空間發(fā)送到用戶空間,這就是熱插拔事件。熱插拔事件會(huì)導(dǎo)致用戶空間中相應(yīng)的處理程序(如udev,mdev)被調(diào)用, 這些處理程序會(huì)通過加載驅(qū)動(dòng)程序, 創(chuàng)建設(shè)備節(jié)點(diǎn)等來響應(yīng)熱插拔事件。
4、熱插拔事件操作集合
????? Struct kset_uevent_ops {
int (*filter)(struct kset *kset, struct kobject *kobj);
const char *(*name)(struct kset *kset, struct kobject *kobj);
int (*uevent)(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env);
}
kset_uevent_ops這三個(gè)函數(shù)什么時(shí)候調(diào)用?
當(dāng)該kset所管理的kobject和kset狀態(tài)發(fā)生變化時(shí)(如被加入,移動(dòng)),這三個(gè)函數(shù)將被調(diào)用。(例:kobject_uevent調(diào)用)
這三個(gè)函數(shù)的功能是什么?
?????? 1)filter:決定是否將事件傳遞到用戶空間。如果filter返回0,將不傳遞事件。(例: uevent_filter)
?????? 2)name:用于將字符串傳遞給用戶空間的熱插拔處理程序。
?????? 3)uevent:將用戶空間需要的參數(shù)添加到環(huán)境變量中。(例:dev_uevent)
5、 kset實(shí)例分析
????#include <linux/device.h>
??? #include <linux/module.h>
??? #include <linux/kernel.h>
??? #include <linux/init.h>
??? #include <linux/string.h>
??? #include <linux/sysfs.h>
??? #include <linux/stat.h>
??? #include <linux/kobject.h>
??? MODULE_AUTHOR("yinjiabin");
??? MODULE_LICENSE("GPL");
??? struct kset *kset_p;
??? struct kset kset_c;
??? /* 函數(shù)聲明 */
??? void obj_test_release(struct kobject *);
??? ssize_t kobj_test_show(struct kobject *,struct attribute *,char *);
??? ssize_t kobj_test_store(struct kobject *,struct attribute *,const char *,size_t);
??? static struct attribute test_attr =
??? {
??????????? .name = "kobj_config",
??????????? .mode = S_IRWXUGO,
??? };
??? static struct attribute *def_attrs[] =
??? {
??????????? &test_attr,
??????????? NULL,
??? };
??? static struct sysfs_ops obj_test_sysops =
??? {
??????????? .show = kobj_test_show,
??????????? .store = kobj_test_store,
??? };
??? static struct kobj_type ktype =
??? {
??????????? .release = obj_test_release,
??????????? .sysfs_ops = &obj_test_sysops,
??????????? .default_attrs = def_attrs,
};
??? void obj_test_release(struct kobject *kobject)
??? {
??????????? printk("[kobj_test: release!]\n");
??? }
??? ssize_t kobj_test_show(struct kobject *kobject,struct attribute *attr,char *buf)
??? {
??????????? printk("Have show -->\n");
??????????? printk("attrname: %s.\n",attr->name);
??????????? sprintf("buf,%s\n",attr->name);
??????????? return strlen(attr->name) + 2;
??? }
??? ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)
??? {
??????????? printk("Have store -->\n");
??????????? printk("write: %s.\n",buf);
??????????? return size;
??? }
??? static int kset_filter(struct kset *kset,struct kobject *kobj)
??? {
??????? printk("Filter: kobj %s.\n",kobj->name);
??????? return 1;
??? }
??? static const char *kset_name(struct kset *kset,struct kobject *kobj)
??? {
??????? static char buf[20];
??????? printk("Name kobj %s.\n",kobj->name);
??????? sprintf(buf,"%s","kset_name");
??????? return buf;
??? }
??? static int kset_uevent(struct kset *kset,struct kobject *kobj, struct kobj_uevent_env *env)
{
??????? int i = 0;
??????? printk("uevent: kobj %s.\n",kobj->name);
??????? while(i < env->envp_idx)
??????? {
??????????? printk("%s.\n",env->envp[i]);
??????????? i ++;
??????? }
??????? return 0;
??? }
??? static struct kset_uevent_ops uevent_ops =
??? {
??????? .filter = kset_filter,
??????? .name = kset_name,
??????? .uevent = kset_uevent,
??? };
??? static int __init kset_test_init(void)
??? {
??????? int ret = 0;
??????? printk("kset test init!\n");
??????? /* 創(chuàng)建并注冊 kset_p */
??????? kset_p = kset_create_and_add("kset_p",&uevent_ops,NULL);
??????? kobject_set_name(&kset_c.kobj,"kset_c");
??????? kset_c.kobj.kset = kset_p;
??????? /* 對于較新版本的內(nèi)核,在注冊 kset 之前,需要 ?
???????????? * 填充 kset.kobj 的 ktype 成員,否則注冊不會(huì)成功 */
??????? kset_c.kobj.ktype = &ktype;
??????? ret = kset_register(&kset_c);
??????? if(ret)
??????????? kset_unregister(kset_p);
??????? return 0;
??? }
??? static void __exit kset_test_exit(void)
??? {
??????? printk("kset test exit!\n");
??????? kset_unregister(kset_p);
??????? kset_unregister(&kset_c);
??? }
??? module_init(kset_test_init);
??? module_exit(kset_test_exit);
總結(jié)
以上是生活随笔為你收集整理的linux设备驱动模型之 kset原理与实例分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 设备模型之 (kobject
- 下一篇: linux设备驱动模型 - device