点击上方蓝字【囧囧妹】一起学习,一起成长!
一、开篇
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_RELEASEstruct delayed_work release;#endifunsigned 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结构体并注册进sysfsstruct 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 0x01static 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 LicenseMODULE_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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




