欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

sysfs--kobject

程序员文章站 2022-06-03 22:58:24
...

写再前面: 

sysfs就是所说的虚拟虚拟文件系统。道行太浅,原理性的东西自己都说不太清,就不瞎写误人子弟了。

可以看下搜寻的几篇帖子,讲的还不错,看完你应该有所收获吧。

https://blog.csdn.net/u010743406/article/details/107694951

 

对于这些东西直接干示例,理解最直观了。不论是kobject还是kset的示例都是参考内核的示例。

自己会下载内核代码吧,下了后搜索kobject-example.c文件,就是我学习的示例。

 

理解:

忍不住讲下自己的理解。哈哈。

对于内核态的代码,用户态访问不到。内核提供了IOCtl和sysfs两种方案。个人感觉sysfs更灵活。

sysfs就是在/sys/xxx路径下创建一个文件夹,并在文件夹下创建若干个文件。

在用户态我们可以使用cat、echo读写文件,从而读写内核态的数据。

 

示例:

在/sys/kernel路径下挂在一个叫做“kobject_example”的文件夹,并在其下创建baz的文件。

通过在/sys/kernel/kobject_example读写baz文件,来达到读写内核态的数据目的。

#include <linux/module.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/init.h>

/*这几个变量用于读写文件的打印;用于文件名*/
static int baz;

/*函数的参数这几个必须有,不然编译不过*/
static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
	int var;
	
	printk("%s[%d]\n", __func__, __LINE__);
	
	if(strcmp(attr->attr.name, "baz") == 0)
	{
		var = baz;
	}
	
	return sprintf(buf, "%d\n", var);
}

/*函数的参数这几个必须有,不然编译不过*/
static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
	int var,ret;
	
	printk("%s[%d]\n", __func__, __LINE__);
	
	/*将字符串转化为int*/
	ret = kstrtoint(buf, 10, &var);
	if(ret < 0)
	{
		return ret;
	}
	
	if(strcmp(attr->attr.name, "baz") == 0)
	{
		baz = var;
	}
	
	return count;
}

/*初始化baz_attribute
__ATTR(name, mode, show, store);
__ATTR里有个巧妙的用法,__stringify(_name)将int型变量名转化为字符串,变成文件名
*/
static struct kobj_attribute baz_attribute = 
	__ATTR(baz, 0664, b_show, b_store);

/*属性组成员*/
static struct attribute *attrs[] = {
	&baz_attribute.attr,
	NULL,
};
static struct attribute_group attr_group ={
	//.attrs是二级指针
	.attrs = attrs,
};

static struct kobject *kobj;
static int __init kboject_init(void)
{
	int retval;
	
	printk("%s[%d]\n", __func__, __LINE__);
	
	/*执行完kobject_create_and_add,会在/sys/kernel路径下创建kboject_example文件夹*/
	kobj = kobject_create_and_add("kboject_example",kernel_kobj);
	if(!kobj)
	{
		return -ENOMEM;
	}
	
	/*执行完sysfs_create_group,会在/sys/kernel/kboject_example创建属性组中定义的文件*/
	retval = sysfs_create_group(kobj, &attr_group);
	if(retval)
		kobject_put(kobj);
	
	return retval;
}

static void __exit kboject_exit(void)
{
	printk("%s[%d]\n", __func__, __LINE__);
	kobject_put(kobj);
}

module_init(kboject_init);
module_exit(kboject_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Greg Kroah-Hartman <[email protected]>");

Makefiel

ifneq ($(KERNELRELEASE),)
obj-m:=kobject.o
else
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	rm -rf *.ko *.o *.symvers *.cmd *.cmd.o *.mod.c *.order *.cmd 
endif

 

 

读写baz文件测试

[email protected]:/sys/kernel$ ls
boot_params  debug         irq                 kexec_crash_size  mm         rcu_expedited  slab           uevent_seqnum
cgroup       fscaps        kboject_example     kexec_loaded      notes      rcu_normal     tracing        vmcoreinfo
config       iommu_groups  kexec_crash_loaded  livepatch         profiling  security       uevent_helper
[email protected]:/sys/kernel$ cd ./kboject_example/
[email protected]:/sys/kernel/kboject_example$ ls
baz
[email protected]:/sys/kernel/kboject_example$ cat baz 
0
[email protected]:/sys/kernel/kboject_example$ echo 2 > baz 
-bash: baz: Permission denied
[email protected]:/sys/kernel/kboject_example$ su
Password: 
[email protected]:/sys/kernel/kboject_example# echo 2 > baz
[email protected]:/sys/kernel/kboject_example# cat baz
2

dmesg打印:

我在每个函数中加入了printk打印,便于理解函数执行。

执行下面命令监控dmesg

watch "dmesg|tail -n 20"

监控结果:

[143666.698254] kboject_init[10]
[143703.990046] kboject_exit[16]
[146363.153040] kboject_init[73]
[146402.610407] b_show[19]
[146418.206658] b_store[34]
[146481.251760] b_show[19]

 

推荐阅读