Linux内核模块开发 第 8 章

The Linux Kernel Module Programming Guide

8 sysfs: 与模块交互

sysfs 允许用户通过读写模块中的变量实现与内核模块的交互。这个特性在调试时比较有用,有时也用作脚本接口(interface for scripts)。可以用如下命令在系统中的 /sys 目录下找到 sysfs 目录。

ls -l /sys

kobjects 的属性(attributes)可以以文件系统中常规文件的形式导出。sysfs 将文件 I/O 操作转发到为属性定义的方法,从而提供读取和写入内核属性(可以理解为上面提到的“模块中的变量”)的方法。

属性定义形如(definition in simply):

struct attribute {
    
     
    char *name; 
    struct module *owner; 
    umode_t mode; 
}; 
 
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr); 
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);

例如,驱动模型将 struct device_attribute 定义为:

struct device_attribute {
    
     
    struct attribute attr; 
    ssize_t (*show)(struct device *dev, struct device_attribute *attr, 
                    char *buf); 
    ssize_t (*store)(struct device *dev, struct device_attribute *attr, 
                    const char *buf, size_t count); 
}; 
 
int device_create_file(struct device *, const struct device_attribute *); 
void device_remove_file(struct device *, const struct device_attribute *);

为了读写属性,声明变量的同时也应该指定对应的 show()store() 方法。include/linux/sysfs.h 中提供了一些宏定义 ( __ATTR , __ATTR_RO , __ATTR_WO , etc.) , 以便提高代码的简洁性和可读性 (making code more concise and readable)。

下面给出了一个hello world模块的示例,其中包括创建可通过sysfs访问的变量。

/* 
 * hello-sysfs.c sysfs example 
 */ 
#include <linux/fs.h> 
#include <linux/init.h> 
#include <linux/kobject.h> 
#include <linux/module.h> 
#include <linux/string.h> 
#include <linux/sysfs.h> 
 
static struct kobject *mymodule; 
 
/* the variable you want to be able to change */ 
static int myvariable = 0; 
 
static ssize_t myvariable_show(struct kobject *kobj, 
                               struct kobj_attribute *attr, char *buf) 
{
    
     
    return sprintf(buf, "%d\n", myvariable); 
} 
 
static ssize_t myvariable_store(struct kobject *kobj, 
                                struct kobj_attribute *attr, char *buf, 
                                size_t count) 
{
    
     
    sscanf(buf, "%du", &myvariable); 
    return count; 
} 
 
static struct kobj_attribute myvariable_attribute = 
    __ATTR(myvariable, 0660, myvariable_show, (void *)myvariable_store); 
 
static int __init mymodule_init(void) 
{
    
     
    int error = 0; 
 
    pr_info("mymodule: initialised\n"); 
 
    mymodule = kobject_create_and_add("mymodule", kernel_kobj); 
    if (!mymodule) 
        return -ENOMEM; 
 
    error = sysfs_create_file(mymodule, &myvariable_attribute.attr); 
    if (error) {
    
     
        pr_info("failed to create the myvariable file " 
                "in /sys/kernel/mymodule\n"); 
    } 
 
    return error; 
} 
 
static void __exit mymodule_exit(void) 
{
    
     
    pr_info("mymodule: Exit success\n"); 
    kobject_put(mymodule); 
} 
 
module_init(mymodule_init); 
module_exit(mymodule_exit); 
 
MODULE_LICENSE("GPL");

Make and install the module:

make 
sudo insmod hello-sysfs.ko

Check that it exists:

sudo lsmod | grep hello_sysfs

What is the current value of myvariable ?

cat /sys/kernel/mymodule/myvariable

Set the value of myvariable and check that it changed.

echo "32" > /sys/kernel/mymodule/myvariable 
cat /sys/kernel/mymodule/myvariable

Finally, remove the test module:

sudo rmmod hello_sysfs

在上面的例子中,我们使用一个简单的 kobject 在 sysfs 下创建了一个目录并与其属性通信。从 Linux v2.6.0 开始,kobject 结构就出现了。它最初旨在作为统一内核代码的简单方法,用于管理引用计数的对象。经过一些任务蠕变,它现在是大部分设备模型与其 sysfs 接口之间的中间件(glue)。

Documentation/driver-api/driver-model/driver.rst and https://lwn.net/Articles/51437/. 有关于 kobject 和 sysfs 的更多信息。

猜你喜欢

转载自blog.csdn.net/qq_33904382/article/details/131586906