linux设备驱动模型之 kset原理与实例分析
1、 Kset
???????kset是具有相同類型的kobject的集合,在sysfs中體現成一個目錄,在內核中用kset數據結構表示,定義為:
struct kset {
struct list_head list; //連接該kset中所有kobject的鏈表頭
spinlock_t list_lock;
struct kobject kobj; //內嵌的kobject
struct kset_uevent_ops *uevent_ops; //處理熱插拔事件的操作集合
}
2、 Kset操作
?????? 1)int kset_register(struct kset *kset)
?????? 在內核中注冊一個kset
?????? 2)void kset_unregister(struct kset *kset)
?????? 從內核中注銷一個kset
3、 熱插拔事件
?????? 在Linux系統中,當系統配置發生變化時,如:添加kset到系統;移動kobject, 一個通知會從內核空間發送到用戶空間,這就是熱插拔事件。熱插拔事件會導致用戶空間中相應的處理程序(如udev,mdev)被調用, 這些處理程序會通過加載驅動程序, 創建設備節點等來響應熱插拔事件。
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這三個函數什么時候調用?
當該kset所管理的kobject和kset狀態發生變化時(如被加入,移動),這三個函數將被調用。(例:kobject_uevent調用)
這三個函數的功能是什么?
?????? 1)filter:決定是否將事件傳遞到用戶空間。如果filter返回0,將不傳遞事件。(例: uevent_filter)
?????? 2)name:用于將字符串傳遞給用戶空間的熱插拔處理程序。
?????? 3)uevent:將用戶空間需要的參數添加到環境變量中。(例:dev_uevent)
5、 kset實例分析
????#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;
??? /* 函數聲明 */
??? 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");
??????? /* 創建并注冊 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;
??????? /* 對于較新版本的內核,在注冊 kset 之前,需要 ?
???????????? * 填充 kset.kobj 的 ktype 成員,否則注冊不會成功 */
??????? 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);
總結
以上是生活随笔為你收集整理的linux设备驱动模型之 kset原理与实例分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 设备模型之 (kobject
- 下一篇: linux设备驱动模型 - device