本文源码均来自linux 3.14.3版本/lib/kobject.c文件

/**
 * kobject_create_and_add - 动态创建一个kobject结构并注册到sysfs
 *
 * @name: kobject的名称
 * @parent: kobject的parent kobject of this kobject, 如果有的话
 *
 * 该方法动态创建一个kobject结构并注册到sysfs。当你完成该结构
 * 之后. 调用kobject_put(),这样该结构在不再使用时将会动态的释放。
 *
 * 如果该kobject无法被创建,将会返回NULL。
 */
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{
        struct kobject *kobj;
        int retval;

kobj = kobject_create();
        if (!kobj)
                return NULL;

retval = kobject_add(kobj, parent, "%s", name);
        if (retval) {
                printk(KERN_WARNING "%s: kobject_add error: %d\n",  __func__, retval);
                kobject_put(kobj);
                kobj = NULL;
        }
        return kobj;
}

/**
 * kobject_create - 动态创建一个kobject结构
 *
 * 动态创建一个kobject结构,并将其设置为一个带默认释放方法的
 * 动态的kobject。
 *
 * 如果无法创建kobject,将会返回NULL。从这里返回的kobject 结构释放
 * 必须调用kobject_put() 方法而不是kfree(),因为kobject_init()已经被调用
 * 过了。
 */
struct kobject *kobject_create(void)
{
        struct kobject *kobj;

kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
        if (!kobj)
                return NULL;

kobject_init(kobj, &dynamic_kobj_ktype);
        return kobj;
}

/**
 * kobject_init - 初始化一个kobject结构
 * @kobj: 指向要初始化的kobject的指针
 * @ktype: 指向该kobject 的ktype的指针
 *
 * 该方法会正确的初始化一个kobject来保证它可以被传递给kobject_add()
 * 调用.
 *
 * 该功能被调用后,kobject必须通过调用kobject_put()来清理,而不是直接
 * 调用kfree,来保证所有的内存都可以被正确的清理。
 */
void kobject_init(struct kobject *kobj, struct kobj_type *ktype)
{
        char *err_str;

if (!kobj) {
                err_str = "invalid kobject pointer!";
                goto error;
        }
        if (!ktype) {
                err_str = "must have a ktype to be initialized properly!\n";
                goto error;
        }
        if (kobj->state_initialized) {
                /* do not error out as sometimes we can recover */
                printk(KERN_ERR "kobject (%p): tried to init an initialized object, something is seriously wrong.\n", kobj);
                dump_stack();
}

kobject_init_internal(kobj);
        kobj->ktype = ktype;
        return;

error:
        printk(KERN_ERR "kobject (%p): %s\n", kobj, err_str);
        dump_stack();
}

static void kobject_init_internal(struct kobject *kobj)
{
        if (!kobj)
                return;
        kref_init(&kobj->kref);
        INIT_LIST_HEAD(&kobj->entry);
        kobj->state_in_sysfs = 0;
        kobj->state_add_uevent_sent = 0;
        kobj->state_remove_uevent_sent = 0;
        kobj->state_initialized = 1;
}

/**
 * kobject_add - kobject添加主方法
 * @kobj: 要添加的kobject
 * @parent: 指向父kobject的指针
 * @fmt: kobject带的名称格式
 *
 * 本方法中会设置kobject名称并添加到kobject阶层。
 *
 * 如果设置了@parent, 那么@kobj的parent将会被设置为它.
 * 如果 @parent为空, 那么该@kobj的 parent会被设置为与该kobject
 * 相关联的.  如果没有kset分配给这个kobject,那么该kobject会放在
 * sysfs的根目录。
 *
 * 如果该方法返回错误,必须调用 kobject_put()来正确的清理该object
 * 相关联的内存。
 * 在任何情况下都不要直接通过调用to kfree()来直接释放传递给该方法
 * 的kobject,那样会导致内存泄露。
 *
 * 注意,该调用不会创建"add" uevent, 调用方需要为该object设置好所有
 * 必要的sysfs文件,然后再调用带UEVENT_ADD 参数的kobject_uevent() 
 * 来保证用户控件可以正确的收到该kobject创建的通知。
 */
int kobject_add(struct kobject *kobj, struct kobject *parent,
const char *fmt, ...)
{
        va_list args;
        int retval;

if (!kobj)
                return -EINVAL;

if (!kobj->state_initialized) {
                printk(KERN_ERR "kobject '%s' (%p): tried to add an "
                      "uninitialized object, something is seriously wrong.\n",
                kobject_name(kobj), kobj);
                dump_stack();
                return -EINVAL;
        }
        va_start(args, fmt);
        retval = kobject_add_varg(kobj, parent, fmt, args);
        va_end(args);

return retval;
}

static int kobject_add_varg(struct kobject *kobj, struct kobject *parent,
   const char *fmt, va_list vargs)
{
        int retval;

retval = kobject_set_name_vargs(kobj, fmt, vargs);
        if (retval) {
                printk(KERN_ERR "kobject: can not set name properly!\n");
                return retval;
}
        kobj->parent = parent;
        return kobject_add_internal(kobj);
}

/**
 * kobject_set_name_vargs - 设置一个kobject的名称
 * @kobj: 要设置名称的kobject
 * @fmt: 用来构建名称的字符串格式
 * @vargs: 构建字符串的参数
 */
int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
 va_list vargs)
{
        const char *old_name = kobj->name;
        char *s;

if (kobj->name && !fmt)
                return 0;

kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
        if (!kobj->name) {
                kobj->name = old_name;
                return -ENOMEM;
        }

/* ewww... some of these buggers have '/' in the name ... */
        while ((s = strchr(kobj->name, '/')))
                s[0] = '!';

kfree(old_name);
        return 0;
}

kobject_add_internal源码前面已经粘贴过了,这里就不再继续粘贴了

kobject_create_and_add解析相关推荐

  1. golang通过RSA算法生成token,go从配置文件中注入密钥文件,go从文件中读取密钥文件,go RSA算法下token生成与解析;go java token共用

    RSA算法 token生成与解析 本文演示两种方式,一种是把密钥文件放在配置文件中,一种是把密钥文件本身放入项目或者容器中. 下面两种的区别在于私钥公钥的初始化, init方法,需要哪种取哪种. 通过 ...

  2. List元素互换,List元素转换下标,Java Collections.swap()方法实例解析

    Java Collections.swap()方法解析 jdk源码: public static void swap(List<?> list, int i, int j) {// ins ...

  3. 条形码?二维码?生成、解析都在这里!

    二维码生成与解析 一.生成二维码 二.解析二维码 三.生成一维码 四.全部的代码 五.pom依赖 直接上代码: 一.生成二维码 public class demo {private static fi ...

  4. Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件)

    1. viper 特点 viper 是一个完整的 Go应用程序的配置解决方案,它被设计为在应用程序中工作,并能处理所有类型的配置需求和格式.支持特性功能如下: 设置默认值 读取 JSON.TOML.Y ...

  5. Go 学习笔记(77)— Go 第三方库之 cronexpr(解析 crontab 表达式,定时任务)

    cronexpr 支持的比 Linux 自身的 crontab 更详细,可以精确到秒级别. ​ 1. 实现方式 cronexpr 表达式从前到后的顺序如下所示: 字段类型 是否为必须字段 允许的值 允 ...

  6. mybatis配置文件解析

    mybatis配置文件解析 mybatis核心配置文件`mybatis-config.xml文件. mybatis的配置文件包含了会深深影响mybatis行为的设置和属性信息. 能配置的内容: con ...

  7. 谷歌BERT预训练源码解析(二):模型构建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_39470744/arti ...

  8. Python 标准库之 xml.etree.ElementTree xml解析

    Python 标准库之 xml.etree.ElementTree Python中有多种xml处理API,常用的有xml.dom.*模块.xml.sax.*模块.xml.parser.expat模块和 ...

  9. 谷歌BERT预训练源码解析(三):训练过程

    目录 前言 源码解析 主函数 自定义模型 遮蔽词预测 下一句预测 规范化数据集 前言 本部分介绍BERT训练过程,BERT模型训练过程是在自己的TPU上进行的,这部分我没做过研究所以不做深入探讨.BE ...

最新文章

  1. 多线程pthread_join()的作用
  2. 自定义scoll样式
  3. 鸟哥:程序员应该不断提升自身的不可替代性
  4. PHP curl get post通用类
  5. python数据库连接池neo4j_在python中操作neo4j数据库的方法
  6. 离散数学-集合运算基本法则
  7. 嵌入式linux 中文输入法,基于嵌入式Linux的汉字输入法
  8. 工业计算机摇杆接口,使用摇杆模块控制计算机鼠标
  9. 【整理】爬取网页数据的方法汇总
  10. 2022年P气瓶充装考题及答案
  11. yocs_velocity_smoother源码编译
  12. 应用程序无法正常启动(oxc000007b):解决方案
  13. 服务器金属外壳刮花了怎么修复,pc拉杆箱被磨了怎么办?3方法快速修复(附防刮方式)...
  14. 微信支付商户证书cert.zip中缺少rootca.pem文件解决方法
  15. 陌生人邀请我加入CS:GO游戏,我一接受就被盗号了
  16. 【总结】DeepCTR如何构建模型
  17. 【GAOPS050】自同步加扰和帧同步加扰
  18. 条件极值(拉格朗日乘数法)_Simplelife_新浪博客
  19. python编程练习:提取Visual MODFLOW水均衡数据(.ZOT)文件至表格
  20. mt4编码限制窗口大小代码_1.5 外汇交易基础:MT4-5 使用指南

热门文章

  1. python对Excel数据进行读写操作
  2. python代码少的作品_世界上有哪些代码量很少,但很牛逼很经典的算法或项目案例?...
  3. C++导入导出动态库
  4. Python脚本运行出现语法错误:IndentationError: unindent does not match any outer indentation level
  5. ubuntu16.04 升级内核
  6. NativeScaler()与loss_scaler
  7. pycharm引入其他目录的包报错,import报错
  8. Mybatis(16)注解开发环境搭建
  9. vue 跨域问题 - 总结篇
  10. phpcms v9宽字节注入问题