暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一起撸linux内核27-初探kobject

囧囧妹 2022-05-15
139

点击上方蓝字【囧囧妹】一起学习,一起成长!

一、开篇

接上一节一起撸linux内核26-内核串口驱动分析

kobject模块是linux设备模型的基础,linux设备模型是使用bus、class、device、driver四个核心数据结构将大量的、不同功能的硬件设备以树状结构的形式进行归纳、抽象,从而方便内核的统一管理。

设备模型有什么优势呢?

      • 代码复用性强多个设备可以复用一个驱动

      • 方便资源的动态申请释放;

      • 提供热插拔机制hotplug/uevent;

      • 设备模型借鉴了oop的思想;


二、kobject

主要涉及的文件内核源码/lib/kobject.c和内核源码/include/linux/kobject.h

    struct kobject {
    const char *name;
    struct list_head entry;
    struct kobject *parent;
    struct kset *kset;
    struct kobj_type *ktype;
    struct kernfs_node *sd;
    struct kref kref;
    #ifdef CONFIG_DEBUG_KOBJECT_RELEASE
    struct delayed_work release;
    #endif
    unsigned int state_initialized:1;
    unsigned int state_in_sysfs:1;
    unsigned int state_add_uevent_sent:1;
    unsigned int state_remove_uevent_sent:1;
    unsigned int uevent_suppress:1;
    };

    核心结构体kobject ,里面的name很关键,它就是我们经常在/sys/下看见的文件名。里面还有一个parent指针,通过该指针可以把不同层次的kobject组织起来。kref里有一个refcount原子计数用来统计该kobject被引用的次数,当引用计数减少到0时可以通过释放接口来释放掉kobject内存。

    我们通过一个简单的示例来了解一下。

    涉及的api有这么几个:



      //动态创建一个kobject结构体
      struct kobject *kobject_create(void)
      //动态创建一个kobject结构体并注册进sysfs
      struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
      //初始化kobject结构
      void kobject_init(struct kobject *kobj, struct kobj_type *ktype)


      //为kobject结构赋值
      int kobject_add(struct kobject *kobj, struct kobject *parent,
      const char *fmt, ...


      //初始化kobject结构并赋值,是koject_init和kobject_add的结合体
      int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype,
      struct kobject *parent, const char *fmt, ...)


      //从设备层次删除kobject结构
      void kobject_del(struct kobject *kobj)


      //kobject引用计数加1,同时返回该结构指针
      struct kobject *kobject_get(struct kobject *kobj)


      //减少引用计数如果引用计数为0则调用kobject_release清除kobject结构
      void kobject_put(struct kobject *kobj)

      我们通过一个内核驱动来简单展示一下,代码如下:



        /**
        * @file kobject.c
        * @brief
        * @author zshare
        * @version v1.0
        * @date 2022-05-15
        * @history
        */


        #include <linux/module.h>//对应内核源码中include/linux/module.h
        #include <linux/moduleparam.h>
        #include <linux/kernel.h>
        #include <linux/init.h> 包含了module_init和module_exit的声明
        #include <linux/cdev.h> 包含字符设备操作函数
        #include <linux/fs.h> 包含文件接口操作函数
        #include <linux/uaccess.h>
        #include <asm/atomic.h>
        #include <linux/slab.h>


        #define _log_
        #ifdef _log_
        #define kernel_print(format, arg...) printk(format,## arg)
        #else
        #define kernel_print(format, arg...) do{}while(0)
        #endif
        #define VERSION "V1.0"
        typedef unsigned char u8;
        typedef unsigned short u16;
        typedef unsigned int u32;
        #define nil NULL
        #define CMD_GET_VERSION 0x01


        static struct kobject *kobj_test;


        static int __init kobject_test_init(void){
        kobj_test = kobject_create_and_add("hello", kernel_kobj);
        if(!kobj_test){
        printk("kobject create failed!\n");
        return -ENOMEM;
        }
        return 0;
        }


        static void __exit kobject_test_exit(void){
        kobject_put(kobj_test);
        }


        module_init(kobject_test_init);
        module_exit(kobject_test_exit);


        MODULE_LICENSE("GPL");//软件代码接受的许可协议General Public License
        MODULE_AUTHOR("Share");//声明作者
        MODULE_DESCRIPTION("kobject test module");//模块简单的描述
        MODULE_VERSION(VERSION);//模块版本
        MODULE_ALIAS("route");//模块在用户空间的别名


        我们make编译一下,并查看一下/sys/kernel/下的文件:

        插入ko文件再来看/sys/kernel/

        可以看见我们在驱动中注册的hello目录,该目录下什么都没有因为我们只进行了注册,并没有进行任何操作。通过rmmod卸载ko后改目录也就跟着消失了。



        觉得不错,点击“分享”,“赞”,“在看”传播给更多热爱嵌入式的小伙伴吧!

        文章转载自囧囧妹,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论