kobject和kset

kobjectkset

首先介绍Sys文件系统:基于RAM的文件系统,把内核数据结构以及他们之间的属性和关系展示给用户,从linux2.6引入,sysproc同类级别属于内存的文件系统,设备和总线驱动模型就在sysfs中,被加载到 /sys/目录下,子目录包括

1Block:里面存放块设备的信息,系统中每个块设备在该目录下都会有一个子目录。

2Bus:在Linux中注册的每一条总线在Bus目录下都会有一个子目录,如pcii2c,并且在每个总线目录里面又包含两个子目录,有devicedriver目录,device里存放挂载在该总线上的设备,driver包含注册到该总线的所有驱动。

3Class:按照功能对设备进行分类。4Device:所有的设备。5Kernel:内核中的配置参数。Module:系统中所有模块的信息。6FirmWare:系统中的固件。 

7Fs:系统中用到的文件系统。 8Power:电源

下图反映sys中文件目录之间的关系,系统中一个设备按照不同的划分方法可能存在于三个不同目录下,比如鼠标在Class目录是输入设备,在Buses目录是USB设备,在Devices目录是所有设备中的一个,最终都指到一个设备,在系统中看到的是一个链接,

[aaa@localhost usbmon]$ ll usbmon0

lrwxrwxrwx. 1 root root 0 Feb 22 23:30 usbmon0 -> ../../devices/virtual/usbmon/usbmon0

usbmon0 这个设备有个软链接,往上链到DeviceBuses里某个目录,


Kobject:实现了面向对象的机制,在机制中充当父类的角色,后面很多对象结构都包含kobject,这些对象就包含kobject的功能,每个kobject对象对应sysfs文件系统中的一个目录,作用:创建sys下的目录。

下面看怎么注册kobject

void kobject_init(struct kobject *kobj, struct kobj_type *ktype) 初始化kobject结构

 

int kobject_add(struct kobject *kobj, struct kobject *parent,

const char *fmt, ...) 添加到系统

 

int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,

 struct kobject *parent, const char *fmt, ...)

初始化kobject,并将其注册到Linux系统

 

void kobject_del(struct kobject *kobj) 删除kobject对象

 

Kobject中的ktype成员是一个指向kobj_type结构的指针,记录了kobject对象的一些属性。

struct kobj_type  {

void  (*release) (struct  kobject *kobj)  ;

struct sysfs_ops *sysfs_ops ;  

struct attribute **default_attrs ; 

};

struct attribute {

char *name ; //属性文件名

struct module *owner ; //拥有者

mode_t mode ; //属性保护位  

}  

Kobject的一个属性struct attribute就对应了kobject目录下的一个文件,name就是文件名。

struct sysfs_ops {

ssize_t (*show)(struct kobject *, struct attribute *,char *);

ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);

};

由两个函数指针构成 show:第一、第二个参数都是内核传给我们的,第三个参数需要我们传给内核,当用户读属性文件时,该函数被调用,该函数将属性值存入buffer中并返还给用户态。

store:当用户写的时候函数调用,存储用户传入的属性值,值从用户处来。

 

  #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>
   
  
  MODULE_LICENSE("Dual BSD/GPL");
   
  void obj_test_release(struct kobject *kobject);
  ssize_t kobj_test_show(struct kobject *kobject, struct attribute *attr,char *buf);
  ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr,const char *buf, size_t count);
   
  struct attribute test_attr = {
          .name = "kobj_config",
          .mode = S_IRWXUGO,
  };	//属性名name是文件名kobj_config,mode是文件读写权限
   
  static struct attribute *def_attrs[] = {
          &test_attr,
          NULL,
  };	//指针数组,每个指针代表一个文件,这里只有一个文件test_attr
   
   
  struct sysfs_ops obj_test_sysops =
  {
          .show = kobj_test_show,
          .store = kobj_test_store,
  };	//show和store是读写test_attr文件时调用
   
  struct kobj_type ktype = 
  {
          .release = obj_test_release,
          .sysfs_ops=&obj_test_sysops,
          .default_attrs=def_attrs,
  };	//ktype赋值记录kobject属性和操作
   
  void obj_test_release(struct kobject *kobject)
  {
          printk("eric_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 count)
  {
          printk("havestore\n");
          printk("write: %s\n",buf);
          return count;
  }	
   
  struct kobject kobj;
  static int kobj_test_init()
  {
          printk("kboject test init.\n");
          kobject_init_and_add(&kobj,&ktype,NULL,"kobject_test");
  //初始化并添加一个kobject,parent父目录为NULL,目录创建在sys目录
          return 0;
  }
   
  static int kobj_test_exit()
  {
          printk("kobject test exit.\n");
          kobject_del(&kobj);
          return 0;
  }
   
  module_init(kobj_test_init);
  module_exit(kobj_test_exit);
  

Kobject用来创建sys文件系统下的目录的,其他结构包含他其他结构也能在sys文件系统下创建目录。Kobject里有属性,属性对应文件,初始化注册kobject

 

KSET

Kset是相同类型kobject的集合,对应的也是目录,是Kobject父母,可以包含目录,kobject不能包含目录,只能包含文件,如果想在目录里包含目录就用kset

int kset_register(struct kset *k)  注册一个kset

void kset_unregister(struct kset *k) 注销kset

Kset在使用时会引起热插拔事件,比如添加kset到系统,移动kobject,因为sys目录里的文件发生变化,会把信息从内核空间通知到用户空间,应用程序就会处理。

热插拔事件由一个结构(包含三个指针)处理,

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的子目录kobjectkset状态发生变化时(如被加入,移动),上面三个函数将被调用。

Filter:可以决定当事件产生时,是否可以把这个事件传给用户空间,返回1函数执行。

Name:用于将字符串传给用户空间的热插拔处理程序。

Uevent:将用户空间需要的参数添加到环境变量(告诉用户触发事件的类型)。

 

 

  #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>
   
  
   
  struct kset kset_p;
  struct kset kset_c;
  
  int kset_filter(struct kset *kset, struct kobject *kobj)
  {
          printk("Filter: kobj %s.\n",kobj->name);
          return 1;
  }	//首先调用,决定剩下两个函数要不要,过滤作用
   
  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;
  }	//kset名
   
  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;
  }	 //把事件告诉用户空间
  
  struct kset_uevent_ops uevent_ops = 
  {
          .filter = kset_filter,
          .name   = kset_name,
          .uevent = kset_uevent,
  };
   
  int kset_test_init()
  {
          printk("kset test init.\n");
          kobject_set_name(&kset_p.kobj,"kset_p");	//第一个kset_p
          kset_p.uevent_ops = &uevent_ops;
   //处理热插拔事件,当kset下的目录发生变化时
          kset_register(&kset_p);		//系统中添加一个目录
   
          kobject_set_name(&kset_c.kobj,"kset_c");	//
          kset_c.kobj.kset = &kset_p;	//	kset_c.kobject指明kset_c目录属性,.kset用于指明父目录
  //kset_c是子目录,kset_p是父目录,触发热插拔函数
          kset_register(&kset_c);
          return 0;
  }
   
  int kset_test_exit()
  {
          printk("kset test exit.\n");
          kset_unregister(&kset_p);
          kset_unregister(&kset_c);
          return 0;
  }
   
  module_init(kset_test_init);
  module_exit(kset_test_exit);
执行效果



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值