有关/sys的介绍参见此处 https://www.kernel.org/doc/html/latest/admin-guide/sysfs-rules.html
全文来自:http://www.embetronicx.com/tutorials/linux/device-drivers/sysfs-in-linux-kernel/
可以发现,这个目录跟驱动程序有关,里面我们看到的“文件”,都是驱动程序里的参数。(e.g.某LED,供电电压,最大电流,等参数。)
在这里,我们要写代码实现:在/sys/下面放一个我们自己的文件,然后在module里面监听这个文件的动向(写入/读取)。
这个目录比较简易,跟着镜头来随便看看。
/sys
|- /sys/bus
|- /sys/bus/i2c
|- /sys/bus/i2c/devices (directory)
|- ...
|- /sys/bus/i2c/drivers (directory)
|- ...
|- /sys/bus/i2c/drivers_autoprobe (file)
|- /sys/bus/i2c/drivers_probe (file)
|- /sys/bus/i2c/uevent (file)
|- /sys/fs
|- ...
|- ...
文件类型都很普通,要不就是普通的目录,要不就是普通的文件。
注意啦注意啦,请记好以下专有名词:
kobject : (kernel Object)在上面的结构里,每个文件夹,都是一个kobject。由此可见一个kobject可以是另外一个kobject的爹。
- 新建文件夹API
kobject_create_and_add("name", 亲生父母)
- 删除文件夹API
kobject_put(kobject*);
- 新建文件夹API
kobj_attribute : 上面列举的结构里,每个文件,都是一个kobj_attribute。只支持写入/读取string,写代码时候不设缓冲区限制。
- kobj_attribute变量初始化 __ATTR( 名字, 权限, 读函数, 写函数);
- 下面两个的
&attr1.attr
指的是struct kobj_attribute里面的一个下属。 - 新建文件API
sysfs_create_file(kobj*, &attr1.attr)
- 删除文件API
sysfs_remove_file(kobj*, &attr1.attr)
// src/include/linux/kobject.h
struct kobj_attribute {
struct attribute attr; //给“新建文件API”传的正是此变量!
ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count);
};
开始
请确保熟记kobject和kobj_attribute两个专有名词,全文只出现这两个新鲜玩意。
代码分两部分,第一部分构建了struct kobj_attribute attr1变量,第二部分初始化module。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
/*** Part1 Kobj Attribute : attr1 ***/
int ksave_attr1=-1;
ssize_t mypro_show_cb(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
printk ("mypro: show..");
return sprintf(buf, "%d", ksave_attr1);
}
ssize_t mypro_store_cb(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
{
printk ("mypro: store..");
sscanf(buf,"%d",&ksave_attr1);
return count;
}
//注意此处attr1不要加引号!!
struct kobj_attribute attr1 = __ATTR( attr1, 0660, mypro_show_cb, mypro_store_cb);
/*** Part2 Module Init ***/
struct kobject *mypro_kobj;
static int __init myinit (void )
{
printk("MyMod> Installing module.\n");
if ( (mypro_kobj = kobject_create_and_add("mypro_kobj", kernel_kobj)) == NULL ) {
printk("kobject create failure");
return -1;
}
if ( sysfs_create_file(mypro_kobj, &attr1.attr) != 0 ) {
printk("kattribute create failure");
kobject_put(mypro_kobj);
return -1;
}
return 0;
}
static void __exit myexit (void )
{
printk("MyMod> Remove module.\n");
sysfs_remove_file(mypro_kobj, &attr1.attr); // delete file.
kobject_put(mypro_kobj); // delete folder.
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("vrqq <me@vrqq.org>");
好了我们来看一下吧cat /sys/kernel/mypro_kobj/attr1
have fun!