Linux Kernel 之 /sys 目录

@vrqq  February 18, 2018

有关/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*);
  • 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!


添加新评论