20150225 IMX257设备驱动模型之Kset
发布日期:2021-06-29 14:55:51 浏览次数:3 分类:技术文章

本文共 4009 字,大约阅读时间需要 13 分钟。

20150225 IMX257设备驱动模型之Kset

2015-02-25 17:00 李海沿

前面我们实现了一个简单的kobject模型,结果就是成功的在 sysfs的/sys/目录下创建一个kobject的目录,目录下面有attr属性文件,很简单,对kobject的操作其实就是把那四个结构体搞懂就习惯了。博文参考地址:

    下面我们来实现设备驱动模型的kset,kset其实和kobject 是差不多的,唯一的一个驱动就是kset目录下面可以包含kobject目录,而kobject目录下面不能包含目录,只能包含属性文件,为了更好理解,可以说kobject就是kset的简化版。

    好了,下面我们正式开始来实现设备驱动模型kset。

 

一、kset介绍

1. kset结构体

Struct kset{

Struct list_head list; //连接所包含的kobject对象的链表首部

Spinlock_t list_lock; //维护list链表的自旋锁

Struct kobject kobj; //内嵌的kobject结构体,说明kset本身也是一个目录

Struct kset_uevent_ops *uevent_ops; //热插拔事件

}

 

从上面的结构体可以得知:

kset 包含kobject 和 一个kset_uevent_ops 热插拔事件结构体

2. 热插拔事件结构体 kset_uevent_ops

热插拔事件意思就是当kset目录下有任何变动,包括目录的移动,增加目录或者属性文件等操作。

当系统配置发生变化时,如添加kset到系统或移动kobject,一个通知会从内核空间发送到用户空间,这就是热插拔事件。热插拔事件会导致用户空间中的处理程序(如udev,mdev)被调用,这些处理程序会通过加载驱动程序,创建设备节点等来响应热插拔事件。

结构体定义为:

struct kset_uevnt_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);

}

功能:

filter 过滤事件,决定是否产生事件,如果返回0,将不产生事件。

name向用户空间传递一个合适的字符串

uevent通过环境变量传递任何热插拔脚本需要的信息,他会在(udev或mdev)调用之前,提供添加环境变量的机会。

 

3. kset操作函数

void kset_init(struct kset *kset);

int kset_add(struct kset *kset);

int kset_register(struct kset *kset);

void kset_unregister(struct kset *kset);

 

二、程序分析

 

1. 定义kset结构体

 

2. 定义热插拔事件结构体

函数实现:

 

3. 在init初始化函数中

如图所示,

第45行: kobject_set_name 是设定kset中的kobject的名字为kset_p

第46行: 关联kset与热插拔时间处理函数

第47行: 注册kset, 此时会在sys目录下创建一个名字为kobject的名字的文件夹

第50行: 设置kset_p的父目录(父kset)为kset_p(注意这一行)

 

4. 在exit函数中,卸载kset

 

5.总体流程分析

1.kset_test_init初始化kset

2.kobject_set_name(&kset_p.kobj,"kset_p");

3.创建一个struct kset kset_p,目录名字是kset_p

4.注册kset_register(&kset_p);

5.添加一个目录kset_p

6.kobject_set_name(&kset_c.kobj,"kset_c");

7.创建一个struct kset kset_c,目录名字是kset_c

8.kset_c.kobj.kset = &kset_p; kset_c的父目录是kset_p,也就是讲kset_p下有一个目录kset_c

9.注册kset_register(&kset_c);

10.添加一个目录kset_c

11.当在kset_p下增加一个kset_c目录,发生热插拔事件,调用uevent_ops

12.kset_filter被调用,返回0,不传递事件,返回1,传递

13.kset_name打印名字

14.kset_uevent打印相关的信息

 

6.编译测试

 

 

如图所示:

在 sys/目录下 ,产生一个 kset_p 的目录,子目录下还有一个kset_c

然后再看打印信息,可以发现分别调用调用了热插拔时间的三个函数。

注意 ACTION后面 为add,意思就是添加了一个kset目录

目录的路径为DEVPATH = /kset_p/kset_c

 

我们再观察卸载驱动时的变化

可以发现,前面ACTION = remove 意思是移除一个kset目录

 

7.总结

kset和kobject的不同之处就是kset下面可以再次包含kset目录,kobject下只能包含属性文件,

创建kset目录时,首先第一步是定义kset结构体,第二步是实现热插拔的结构体及其相应的函数与,第三步就是在初始化函数中对kset的kobject命名,关联热插拔事件,最后就是注册kset,第四步是当我们不用kset时自然就是卸载kset了。很简单吧。

搞定这个了,下一步我们就开始 总线-设备-驱动模型 之旅了,

 

 

附上驱动程序:

 

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 10 //定义两个kset结构体11 struct kset kset_p;12 struct kset kset_c;13 14 static int kset_filter(struct kset *kset,struct kobject *kobj){15 printk("Filter: kobj %s. \n",kobj->name);16 return 1;17 }18 19 const char *kset_name(struct kset *kset, struct kobject *kobj){20 static char buf[20];21 printk("Name: kobj %s. \n",kobj->name);22 return buf;23 }24 25 static int kset_uevent(struct kset *kset, struct kobject *kobj,struct kobj_uevent_env *env){26 int i = 0;27 printk("uevent : kobj %s. \n",kobj->name);28 29 while(i < env->envp_idx){ //打印相关的信息30 printk("%s .\n",env->envp[i]);31 i++;32 }33 return 0;34 }35 36 //定义kset发生热插拔(目录下有任何变动)时,调用的函数37 struct kset_uevent_ops uevent_ops = {38 .filter = kset_filter,39 .name = kset_name,40 .uevent = kset_uevent,41 };42 43 static int kset_test1_init(void){44 printk("<0>kset test init. \n");45 kobject_set_name(&kset_p.kobj,"kset_p");46 kset_p.uevent_ops = &uevent_ops; //关联热插拔事件处理函数47 kset_register(&kset_p); //注册48 49 kobject_set_name(&kset_c.kobj,"kset_c");50 kset_c.kobj.kset = &kset_p; //执行kset_c的父目录为kset_p51 kset_register(&kset_c); //注册52 53 return 0;54 }55 56 static int kset_test1_exit(void){57 printk("<0>kset test exit. \n");58 kset_unregister(&kset_p); //kset卸载59 kset_unregister(&kset_c);60 return 0;61 }62 63 module_init(kset_test1_init);64 module_exit(kset_test1_exit);65 66 MODULE_AUTHOR("Lover雪儿");67 MODULE_LICENSE("Dual BSD/GPL");

View Code

 

转载地址:https://ciellee.blog.csdn.net/article/details/82599449 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:PHP商城RSS订阅源类开发详解(原创)
下一篇:Ajax快速入门

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年04月19日 20时36分30秒