IMX257 设备驱动模型之Kobject(三)

发布时间:2024-08-15  

一、工作流程:

1. 定义kobject结构体

kboject结构体定义如下:

struct kobject{

    const char *name; //显示在sysfs中的名称

    struct list_head entry;   //下一个kobject结构

    struct kobject *parent;  //指向父kobject结构体,如果存在

    struct kset    *kset;   //指向kset集合

    struct kobj_type   *ktype; //指向kobject类型描述符

    struct sysfs_dirent *sd; //对应sysfs的文件目录

    struct kref kref;   //kobject引用计数

    unsigned int state_initialized:1; //是否初始化

    unsigned int state_in_sysfs:1; //是否加入sysfs

    unsigned int state_add_uevent_sent:1; //是否支持热插

    unsigned int state_remove_uevent_sent:1; //是否支持热拔

}

 

既然定义了kobject结构体,但是这是一个空的结构体,并没有什么属性,所以自然我们就是定义它的属性结构体属性 kobj_type 类描述符

 

2. 定义kobj_type结构体

kobje结构体定义如下:

struct kobj_type

{

  void (*release)(struct kobject *kobj); //释放kobject和其他占用资源的函数

  struct sysfs_ops *sysfs_ops;      //操作属性的方法

  struct attribute **default_attrs;     //属性数组

};

所以自然我们就要实现结构体中的 释放函数,操作属性方法,和属性数组

 

2.1 release函数实现 属性释放方法

这里我们release函数只是简单的打印一句话,实际项目中的release可能包含各种代码,视具体功能而定

 

 

2.2 sysfs_ops结构体 属性操作方法

如图所示,sys_ops中就是定义了对属性文件的读写操作调用的函数

其原型结构体如下:

struct sysfs_ops{

  ssize_t (*show)(struct kobject *,struct attribute *,char *);  //读属性操作函数

  ssize_t (*store)(struct kobject *,struct attribute *,const char *,size_t); //写属性操作函数

};

 

2.3 default_attrs属性数组

在注释中已经讲得很详细了,它也可以理解为在sys的文件夹中的属性文件,结构体就对应属性文件

 

2.3.1 test_attr属性结构体

 

同样在代码中已经解释的很详细了,可以这样理解,这个结构体中所有的属性就是在属性文件中的文件内容

其原型如下:

struct attribute {

const char *name;

struct module *owner;

mode_t mode;

};

 

#define __ATTR(_name,_mode,_show,_store) {

.attr = {.name = __stringify(_name), .mode = _mode },

.show = _show,

.store = _store,

}

 

int __must_check sysfs_create_file(struct kobject *kobj, const struct attribute *attr);

int __must_check sysfs_create_dir(struct kobject *kobj);

 

3. 添加kobject进入内核

到此为止,我们呢已经将kobject基本的属性、方法等都实现了,下面自然就是将它加入结构体,告诉操作系统啊,

我们此处init函数唯一的操作就是将它加入注册进入操作系统,让操作系统认识这个结构体。

 

4. 从内核中删除操作系统

有添加自然就会有删除

如图所示,简简单单的几个字却要这么多话来为它解释。

具体工作流程这里就不赘述了


二、带详细注释的源代码

  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 

  9 //定义一个名为kobject_test,可以读写的属性

 10 //这个结构体就是定义我们 /sys/kobject_test/kobject_test属性文件的属性

 11 //当我们使用cat去读时,

 12 //系统会调用kobject_test_show从而打印出属性文件的name属性

 13 //并且我们可以通过echo 'Lover雪儿' > kobject_test命令去写入时

 14 //系统会调用kobject_test_store将.name这个属性修改为我们自定义的'Lover雪儿'

 15 //总结一下,它的功能就是 /sys/kobject_test/下面的属性文件

 16 struct attribute test_attr = {

 17     .name = 'kobject_test',        //属性名

 18     .mode = S_IRWXUGO,            //属性为可读可写

 19 };

 20 

 21 //我们要使用kobject自然就要定义一个kobject属性

 22 //其实这个结构体就是 会在 /sys/目录下建立一个文件夹 

 23 //文件夹的名字在init函数kobject_init_and_add中定义的那个名字

 24 //总结一下,这个结构体的功能就是在sys目录下建立这个文件夹

 25 //然后我们文件夹中有的属性文件,只要在它下面添加就行了

 26 //该kobject只有一个属性就是前面定义的test_attr

 27 static struct attribute *def_attrs[] = {

 28     &test_attr,

 29     NULL,    

 30 };

 31 

 32 //当kobject的引用计数为0时,会自动调用此函数,

 33 //当我们在exit函数中调用kobject_del(&kobj);时

 34 //在del中主要的操作就是在sysfs中删除kobj

 35 //然后将kboj从kset集合中删除

 36 //然后将kobj的父目录设置为空

 37 //最重要的是将父目录的引用计数设为0 ,

 38 //系统检测到引用计数为0,就会调用此函数

 39 void kobject_test_release(struct kobject *kobject){

 40     printk('kobject_test: kobject_test_release() . n');

 41 }

 42 

 43 //读属性的名字

 44 //在系统空间当我们使用cat命令对属性文件进行读取时,

 45 //系统就会自动调用此函数,将前面我们test_attr的.name属性打印出来

 46 ssize_t kobject_test_show(struct kobject *kobject, struct attribute *attr, char *buf){

 47     printk('call kobject_test_show(). n');        /*调试信息*/

 48     printk('attrname: %s.n',attr->name);    //打印属性名字

 49     sprintf(buf,'%sn',attr->name);        //将名字方法buf中返回用户空间

 50     return strlen(attr->name) + 2;

 51 }

 52 

 53 //写一属性的值

 54 //和前面读属性函数差不多,这里就是把我们的test_attr的.name属性重新赋一个值

 55 ssize_t kobject_test_store(struct kobject *kobject,struct attribute *attr, const char *buf, size_t count){

 56     printk('call kobject_test_store(). n');    /*调试信息*/

 57     printk('write: %s.n',buf);                    //打印属性名字

 58     strcpy(attr->name, buf);                    //写一个属性

 59     return count;

 60 }

 61 

 62 //前面我们实现了对属性文件读和写的方法,

 63 //但是操作系统如何才知道那两个函数时读写函数

 64 //重点就在这里,和以前我们的字符函数file_operation差不多

 65 //这里就是告诉系统,当发生读写操作时,分别调用什么函数

 66 struct sysfs_ops obj_test_sysops = {

 67     .show = kobject_test_show,    //属性读函数

 68     .store = kobject_test_store,    //属性写函数

 69 };

 70 

 71 //后面代码中我们使用struct kobject kobj;

 72 //但是kobj的属性只是一个空的结构体而已

 73 //它又有哪些属性呢,答案就在这里,这里定义了kobject的默认属性

 74 //.realease 当删除kobject时会调用的函数

 75 //.sysfs_ops 当系统对属性文件进行读写是,会调用的函数,也就是前面我们的sysfs_ops这个结构体

 76 //.default_atrs 默认的属性,就是定义我们/sys/kobject/目录下有哪些属性文件

 77 struct kobj_type ktype={

 78     .release = kobject_test_release,    //释放函数

 79     .sysfs_ops = &obj_test_sysops,        //属性的操作函数

 80     .default_attrs = def_attrs,            //默认属性

 81 };

 82 

 83 //此处定义我们的kobject结构体

 84 struct kobject kobj;        //要添加的kobject结构

 85 

 86 //初始化函数

 87 static int kobject_test_init(void){

 88     printk('kobject test_init(). n');

 89 

 90     //此处,就是将我们的kobject函数注册进入系统。

 91     //arg1:既然要注册kobject,此处自然是我们前面定义的kboj这个机构提

 92     //arg2:ktype前面我定义的属性,这里就是将我们的kobject和ktype联系起来

 93     //arg3:此处就是定义kobj的父kobject结构体

 94     //arg4:此处就是定义我们kobject的属性的目录名字

 95     kobject_init_and_add(&kobj, &ktype, NULL, 'kobject_test');

 96 

 97     return 0;

 98 }

 99 

100 static int kobject_test_exit(void){

101     printk('kobject test_exit. n');

102     

103     //前面说过了

104     //当我们在exit函数中调用kobject_del(&kobj);时

105     //在del中主要的操作就是在sysfs中删除kobj

106     //然后将kboj从kset集合中删除

107     //然后将kobj的父目录设置为空

108     //最重要的是将父目录的引用计数设为0 ,

109     //系统检测到引用计数为0,就会调用前面的release函数

110     kobject_del(&kobj);        //删除kobject

111     return 0;

112 }

113 

114 module_init(kobject_test_init);

115 module_exit(kobject_test_exit);

116 

117 MODULE_AUTHOR('Lover雪儿');

118 MODULE_LICENSE('Dual BSD/GPL');


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>