zoukankan      html  css  js  c++  java
  • Linux 内核:sysfs 有关的API

    背景

    相关文章:1、sysfs与kobject基类

    下面内容基本上参考(有删改):https://blog.csdn.net/qb_2008/article/details/6846412

    API

    attribute

    // include/linux/sysfs.h
    #include <linux/sysfs.h>
    struct attribute {
        /* 属性名称 */
        const char      *name;
        /* 访问权限 */
        umode_t         mode;
        // ...
    };
    
    struct attribute_group {
        const char      *name;
        umode_t         (*is_visible)(struct kobject *,
                              struct attribute *, int);
        struct attribute    **attrs;
        struct bin_attribute    **bin_attrs;
    };
    
    struct bin_attribute {
        struct attribute    attr;
        size_t          size;
        void            *private;
        ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
                char *, loff_t, size_t);
        ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
                 char *, loff_t, size_t);
        int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
                struct vm_area_struct *vma);
    };
    

    之前说过普通文件是kobject目录的属性展现。

    struct attribute:就是属性的通用结构,其它部分在使用时还可以把struct attribute内嵌到更大的属性结构中。

    struct bin_attribute:为二进制属性专门设计的,它在sysfs中表现为二进制文件,大多数是设备配置参数的映射。struct bin_attribute恰恰就是把struct attribute内嵌到更大结构的样例。

    struct attribute_group:提供一组属性的集合,这样集中管理attribute与`bin_attribute``更为方便。

    静态初始化属性的宏

    #define __ATTR(_name, _mode, _show, _store) {               
        .attr = {.name = __stringify(_name), .mode = _mode },       
        .show   = _show,                        
        .store  = _store,                       
    }
    
    #define __ATTR_RO(_name) {                      
        .attr   = { .name = __stringify(_name), .mode = S_IRUGO },  
        .show   = _name##_show,                     
    }
    
    #define __ATTR_WO(_name) {                      
        .attr   = { .name = __stringify(_name), .mode = S_IWUSR },  
        .store  = _name##_store,                    
    }
    
    #define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO),     
                 _name##_show, _name##_store)
    
    #define __ATTR_NULL { .attr = { .name = NULL } }
    

    以上的宏是为了静态初始化属性时更为方便,我们简单将其忽略。

    属性读写方法sysfs_ops

    #include <linux/sysfs.h>
    struct sysfs_ops {
        /* 读取该 sysfs 文件时该方法被调用 */
        ssize_t (*show)(struct kobject *, struct attribute *, char *);
        /* 写入该 sysfs 文件时该方法被调用 */
        ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
    };
    

    show()方法在读操作时被调用。它会拷贝由attr提供的属性值到buffer指定的缓冲区中,缓冲区大小为PAGE_SIZE字节;在x86体系中,PAGE_SIZE为4096字节。该函数如果执行成功,则将返回实际写入buffer的字节数。如果失败,则返回负的错误码。

    store()方法在写操作时调用,它会从buffer中读取size大小的字节,并将其存放如attr表示的属性结构体变量中。缓冲区的大小总是为PAGE_SIZE和更小些。该函数如果执行成功,则将返回实际从buffer中读取的字节数。如果失败,则返回负数的错误码。

    工作队列延迟调度

    int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
                    void *data, struct module *owner);
    

    sysfs_schedule_callback()会创建一个工作队列,稍后调用func(data)。

    本来sysfs中的属性读写函数是无法删除属性文件或者kobject目录的,因为调用函数时是加锁的,要删除也需要加锁。但这里可以通过工作队列回调的方式实现。

    本来自己无法删除自己,现在可以了。

    目录操作

    int __must_check sysfs_create_dir(struct kobject *kobj);
    void sysfs_remove_dir(struct kobject *kobj);
    
    int __must_check sysfs_rename_dir(struct kobject *kobj, const char *new_name);
    int __must_check sysfs_move_dir(struct kobject *kobj,
                                    struct kobject *new_parent_kobj);
    

    sysfs_create_dir()创建一个kobject对应的目录,目录名就是kobj->name。

    sysfs_remove_dir()删除kobj对应的目录。删除一个目录也会相应地删除目录下的文件及子目录。

    sysfs_rename_dir()修改kobj对应目录的名称。

    sysfs_move_dir()将kobj对应的目录移到new_parent_kobj对应的目录下。

    属性

    通用属性

    int __must_check sysfs_create_file(struct kobject *kobj,
    				   const struct attribute *attr);
    int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr,
    				  mode_t mode);
    void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
    

    sysfs_create_file()在kobj对应的目录下创建attr对应的属性文件。

    sysfs_chmod_file()修改attr对应的属性文件的读写权限。

    sysfs_remove_file()在kobj对应的目录下删除attr对应的属性文件。

    二进制属性

    int __must_check sysfs_create_bin_file(struct kobject *kobj,
    				       struct bin_attribute *attr);
    void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
    

    sysfs_create_bin_file()在kobj目录下创建attr对应的二进制属性文件。

    sysfs_remove_bin_file()在kobj目录下删除attr对应的二进制属性文件。

    批量操作

    int __must_check sysfs_create_group(struct kobject *kobj,
            const struct attribute_group *grp);
    int sysfs_update_group(struct kobject *kobj,
             const struct attribute_group *grp);
    void sysfs_remove_group(struct kobject *kobj,
       const struct attribute_group *grp);
    int sysfs_add_file_to_group(struct kobject *kobj,
       const struct attribute *attr, const char *group);
    void sysfs_remove_file_from_group(struct kobject *kobj,
       const struct attribute *attr, const char *group);
    

    sysfs_create_group()在kobj目录下创建一个属性集合,并显示集合中的属性文件。如果文件已存在,会报错。

    sysfs_update_group()在kobj目录下创建一个属性集合,并显示集合中的属性文件。文件已存在也不会报错。sysfs_update_group()也用于group改动影响到文件显示时调用。

    sysfs_remove_group()在kobj目录下删除一个属性集合,并删除集合中的属性文件。

    sysfs_add_file_to_group()将一个属性attr加入kobj目录下已存在的的属性集合group。

    sysfs_remove_file_from_group()将属性attr从kobj目录下的属性集合group中删除。

    阻塞IO

    void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr);
    void sysfs_notify_dirent(struct sysfs_dirent *sd);
    

    sysfs_notify()和sysfs_notify_dirent()都是用来唤醒在属性文件上调用select()或poll()而阻塞的用户进程。

    软链接

    int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target,
    				   const char *name);
    int __must_check sysfs_create_link_nowarn(struct kobject *kobj,
    					  struct kobject *target,
    					  const char *name);
    void sysfs_remove_link(struct kobject *kobj, const char *name);
    

    sysfs_create_link()在kobj目录下创建指向target目录的软链接,name为软链接文件名称。

    sysfs_create_link_nowarn()与sysfs_create_link()功能相同,只是在软链接文件已存在时不会出现警告。

    sysfs_remove_link()删除kobj目录下名为name的软链接文件。

    生命周期管理

    struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
    				      const unsigned char *name);
    struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
    void sysfs_put(struct sysfs_dirent *sd);
    

    sysfs_get()增加目录或文件的引用计数。

    sysfs_put()减少目录或文件的引用计数,并在降为零时删除相应的文件或目录,这种删除又会减少上层目录的引用计数。

    sysfs_get_dirent()是增加目录parent_sd中名为name的目录或文件的引用计数。

    虽然同样是引用计数,同样在降为零时有删除动作,但却并非使用kref。这种操作更多地继承了文件系统管理时的传统。

    其他

    初始化函数

    int __must_check sysfs_init(void);
    

    sysfs_init()是在sysfs模块初始化时调用的。

    调试

    void sysfs_printk_last_file(void);
    

    sysfs_printk_last_file()是在sysfs崩溃时打印最后一个访问到的文件路径。

    如果说我的文章对你有用,只不过是我站在巨人的肩膀上再继续努力罢了。
    若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
    博客地址:https://www.cnblogs.com/schips/
  • 相关阅读:
    spring(1)
    mybatis(7)自定义结果集(一对多/多对一)
    延迟加载
    《构建之法》阅读笔记03
    http socket
    转换
    .net后台通过xmlhttp 和远程服务通讯
    XMLHttpRequest介绍
    js 贪吃蛇
    触发器
  • 原文地址:https://www.cnblogs.com/schips/p/linux_kernel_sysfs_api.html
Copyright © 2011-2022 走看看