zoukankan      html  css  js  c++  java
  • kobject和kset的一些学习心得

      #include <linux/module.h>

      #include <linux/kernel.h>

      #include <linux/kobject.h>

      #include <linux/sysfs.h>

      #include <linux/slab.h>

      static struct kobject * parent;

      static struct kobject *child;

      static struct kset *c_kset;

      static unsigned long flag= 1;

      static ssize_t att_show(struct kobject *kobj,struct attribute *attr,char *buf)

      {

      size_t count = 0;

      count += sprintf(&buf[count],"%lu ",flag);

      return count;

      }

      static ssize_t att_store(struct kobject *kobj,struct attribute *attr,

      const char *buf,size_t count)

      {

      flag = buf[0]-'0';

      //通过kobject_uevent来将内核对象kobj的状态变化通知用户程序

      switch(flag){

      case 0:

      kobject_uevent(kobj,KOBJ_ADD);

      break;

      case 1:

      kobject_uevent(kobj,KOBJ_REMOVE);

      break;

      case 2:

      kobject_uevent(kobj,KOBJ_CHANGE);

      break;

      case 3:

      kobject_uevent(kobj,KOBJ_MOVE);

      break;

      case 4:

      kobject_uevent(kobj,KOBJ_ONLINE);

      break;

      case 5:

      kobject_uevent(kobj,KOBJ_OFFLINE);

      break;

      }

      return count;

      }

      static struct attribute cld_att = {

      .name = "cldatt",

      .mode = 0777,

      };

      static const struct sysfs_ops att_ops = {

      .show = att_show,

      .store = att_store,

      };

      static struct kobj_type cld_ktype = {

      .sysfs_ops = &att_ops,

      };

      static int kobj_demo_init(void)

      {

      int err;

      parent = kobject_create_and_add("pa_obj",NULL);

      child = kzalloc(sizeof(*child),GFP_KERNEL);

      if(!child)

      return PTR_ERR(child);

      //一个能够通知用户空间状态变化的kobject必须隶属于某一个kset,也就是所谓的

      //subsystem,所以此处给内核对象child创建一个kset对象c_kset

      c_kset = kset_create_and_add("c_kset",NULL,parent);

      if(!c_kset)

      return -1;

      child->kset = c_kset;

      err = kobject_init_and_add(child,&cld_ktype,NULL,"cld_obj");

      if(err)

      return err;

      err = sysfs_create_file(child,&cld_att);

      return err;

      }

      static void kobj_demo_exit(void)

      {

      sysfs_remove_file(child,&cld_att);

      kset_unregister(c_kset);

      kobject_del(child);

      kobject_del(parent);

      }

      module_init(kobj_demo_init);

      module_exit(kobj_demo_exit);

      MODULE_LICENSE("GPL");

      陈学松大虾的这个例子十分好。赞一个。

      kobject_create_and_add这个函数首先会调用kobject_create来分配并初始化一个kobject对象,

      然后调用kobject_add函数在sysfs文件系统中为新生成的kobject对象建立一个新的目录。那么这个目录建立在

      sysfs文件系统中的哪个位置呢?kobject_add最后是通过sysfs_craete_dir函数来创建一个目录的,看一下这个函数

      的关键代码便能知道

      /*fs/sysfs/dir.c*/

      int sysfs_create_dir(struct kobject *kobj)

      {

      ...

      if(kobj->parent)

      parent_sd = kobj->parent->sd;

      else

      parent_sd = &sysfs_root;

      ...

      error =create_dir(kobj,parent_sd,type,ns,kobject_name(kobj),&sd);

      if(!error)

      kobj->sd = sd;

      return error;

      }

      可以看到,如果kobj->parent字段为空,那么该函数就会调用create_dir在sysfs文件树的根目录下为kobj创建

      一个新的目录,否则就在parent的目录下为该kobj创建一个新的目录。

      kobject_add首先会将参数parent赋值给kobj的parent成员 kobj->parent =parent,然后调用kobject_add_internal(kobj)函数,

      在kobject_add_internal函数内部,如果调用kobject_add时parent是一个NULL指针,那么要看该kobj是否在一个

      kset对象中,如果是就把该kset中的kobject成员作为kobj的parent;否则kobj的parent值仍然为NULL,那么在接下来

      调用sysfs_create_dir的时候,该kobj就会在/sys目录创建一个新的文件夹。

      /*struct kobject * kobject_create_and_add(const char * name,struct kobject *parent)*/

      例如上面的kobject_create_and_add("pa_obj",NULL);这个函数传入的parent为空,那么他将会在/sys下创建一个目录名为pa_obj的新目录。

      /*struct kset *kset_create_and_add(const char *name,

      struct kset_uevent_ops *uevent_ops,

      struct kobject *parent_kobj)*/

      再看下面的kset_create_and_add("c_kset",NULL,parent);kset里面也有一个内嵌的kobject,所以传入的第一个和第三个参数是

      给这个内嵌的kobject用的,第二个参数是给kset用的。

      看一下kset的结构体原形:

      struct kset {

      struct list_head list;

      spinlock_t list_lock;

      struct kobject kobj;

      struct kset_uevent_ops *uevent_ops;

      };

      多么简单,其实kset在sysfs文件系统中没有实体表现的,他不像kobject,一个kobject对应一个sysfs文件系统下的一个目录,kset的存在无法就是为了

      方便管理kobject。

      kset_create_and_add最终也会调用kobject_create_and_add,传入的参数肯定是""c_kset"和parent,那么将会在/sys/pa_obj的目录下面创建

      一个目录名为c_kset的新目录.

      再来看下面的

      child->kset = c_kset;

      err = kobject_init_and_add(child,&cld_ktype,NULL,"cld_obj");

      kobject_init_and_add与kobject_create_and_add的其中一个区别便是前者可以使用自己定义的kobj_type,而后者内核会提供一个默认的kobj_type

      (读者自己深入函数内部就会看到这个默认的kobj_type)。

      这个函数原型为:int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,

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

      上面的程序在调用这个函数的时候把parent设置为NULL,由于在调用这个函数之前有这么一行:child->kset = c_kset,如上所分析的那样,

      由于设置了child所属的kset,那么在kobject_init_and_add内部会把child->parent设置为c_kset->kobj,这意味着将会在/sys/pa_obj/c_kset目录下

      创建一个目录名为cld_obj的新目录,如果你把这kobject_init_and_add参数中的NULL改为parent(parent = kobject_create_and_add("pa_obj",NULL);

      这个parent就是pa_obj的对象kobj),那么这么一改,cld_obj目录就和c_kset目录一样都是在/sys/pa_obj目录之下了。

      再下面的sysfs_create_file是在相应的目录下面创建一个属性文件(注意,现在是创建文件而不是目录了)

      上面几个函数是构建linux设备模型框架的最基本的函数。。如果说linux设备模型是一栋摩天大厦,那么这几个函数就是把这个大厦建立起来的最

      底层的建筑工人。

  • 相关阅读:
    HTTP 501 错误 – 未实现 (Not implemented) 或者是 Failure: Address already in use
    HTTP 400 Bad request 原因
    树莓派 NAS aria2 下载磁力链接无速度
    踩坑备忘之“yarn : 无法加载文件 C:\Users\siazon\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本。"
    架构小试之IDL
    服务端基本概念和指标
    git常用命令
    mysql20211116
    blog JavaJinguo
    android 分享功能
  • 原文地址:https://www.cnblogs.com/Blue-Moon/p/3332765.html
Copyright © 2011-2022 走看看