Linux开发讲课7---Linux sysfs文件系统

一、sysfs文件系统介绍

        Sysfs(System Filesystem)是Linux内核提供的一种虚拟文件系统,用于向用户空间公开有关设备和驱动程序的信息。它类似于/proc文件系统,但是专注于设备和驱动程序信息,而非进程信息。

        Sysfs通过文件和目录的方式组织信息,其中每个文件或目录对应于系统中的一个设备、驱动程序或者其他内核对象。这些文件通常包含有关设备和驱动程序的属性、状态和配置信息。有些文件可以被写入,用于配置和控制设备。

        Sysfs通常被挂载在/sys目录下,它提供了一种方便的方式,让用户空间的程序可以动态地获取和管理系统中的设备信息,而无需直接访问内核数据结构。

二、Kernel Object

        在Linux内核中,Kobject是内核对象(Kernel Object)的抽象表示。它是内核中几乎所有子系统的基础,用于表示这些子系统中的各种对象,如设备、驱动程序、总线等。

        Kobject提供了一个通用的、层次化的对象模型,用于管理内核中的各种对象。每个Kobject都有一个唯一的名称和一个指向其父Kobject的指针,从而组织成一个层次结构。此外,Kobject还可以拥有属性(如设备属性、驱动程序属性等),这些属性可以通过sysfs文件系统向用户空间公开。

        Sysfs是通过Kobject来表示设备、驱动程序等内核对象的信息的一种方式。当内核中的设备、驱动程序等对象被创建时,相应的Kobject也会被创建,然后通过Sysfs将其信息暴露给用户空间。

        struct kobject在头文件"linux/kobject.h"中定义,它通常被嵌入到其他结构体中。

                

其中:

  • kref:提供kobject的引用技术。

  • ktype:kobject关联的类型。

  • kset:指向同一类kobject集合的指针。

  • sd:当前kobject在/sys下的目录条目。

三、Sysfs使用方式

        Linux内核中使用sysfs的步骤比较简单:(1)在/sys路径下创建目录;(2)创建sysfs文件。下面将详细展开这两步涉及的内核API。

3.1、在/sys下创建目录

        struct kobject * kobject_create_and_add ( const char * name, struct kobject * parent);

        Linux内核预定义了几个常用的parent参数:

  1. kernel_kobj:在/sys/kernel下创建目录;

  2. firmware_kobj:在/sys/firmware下创建目录;

  3. fs_kobj:在/sys/fs下创建目录。

        如果parent取值为NULL,则在/sys下面创建目录。

        相应地,如果需要删除对应的sysfs目录,可以用:

        void kobject_put(struct kobject *kobj);

3.2、创建sysfs文件

                sysfs文件可以通过sysfs属性来创建,它定义在头文件"sysfs.h"中:

struct kobj_attribute {  struct attribute attr;  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);};

        

        其中attr表示将要创建的文件(属性),而show和store分别表示对应的sysfs文件在读和写操作时的回调函数。

        struct kobj_attribute可以通过__ATTR宏来创建:

        __ATTR(name, permission, show_ptr, store_ptr);

        准备好attr之后,可以通过sysfs_create_file来创建出sysfs文件:

        int sysfs_create_file ( struct kobject * kobj, const struct attribute * attr);

        同样地,如果需要删除对应的sysfs文件,可以用:

        void sysfs_remove_file ( struct kobject * kobj, const struct attribute * attr);

        将前面介绍的API汇总起来,创建一个sysfs文件的过程代码如下:

        

struct kobj_attribute my_attr = __ATTR(my_value, 0660, sysfs_show, sysfs_store);static ssize_t sysfs_show(struct kobject *kobj,                          struct kobj_attribute *attr, char *buf){    return sprintf(buf, "%d", my_value);}static ssize_t sysfs_store(struct kobject *kobj,                            struct kobj_attribute *attr,const char *buf, size_t count){        sscanf(buf,"%d",&my_value);        return count;}
/*Creating a directory in /sys/kernel/ */kobj_ref = kobject_create_and_add("my_sysfs", kernel_kobj);/*Creating sysfs file for my_value*/if(sysfs_create_file(kobj_ref,&my_attr.attr)){    printk(KERN_INFO"Failed to create sysfs file\n");    goto r_sysfs;}kobject_put(kobj_ref); sysfs_remove_file(kernel_kobj, &my_attr.attr);

四、Sysfs完整代码演示

                kernel_driver.c

        

#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/kdev_t.h>#include <linux/fs.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/slab.h>#include <linux/uaccess.h>#include <linux/kthread.h>#include <linux/wait.h>#include <linux/err.h>
uint32_t read_count = 0;static struct task_struct *wait_thread;
dev_t dev = 0;static struct class *dev_class;static struct cdev my_cdev;wait_queue_head_t my_waitqueue;int waitqueue_flag = 0;
static int wait_function(void *unused){
    while (1)    {        pr_info("Waiting For Event...\n");        wait_event_interruptible(my_waitqueue, waitqueue_flag != 0);        if (waitqueue_flag == 2)        {            pr_info("Event Came From Exit Function\n");            return 0;        }        pr_info("Event Came From Read Function - %d\n", ++read_count);        waitqueue_flag = 0;    }    do_exit(0);    return 0;}
static ssize_t my_read(struct file *filp, char __user *buf, size_t len, loff_t *off){    waitqueue_flag = 1;    wake_up_interruptible(&my_waitqueue);    return 0;}
static struct file_operations fops = {    .owner = THIS_MODULE,    .read = my_read,};
static int __init my_driver_init(void){    if ((alloc_chrdev_region(&dev, 0, 1, "my_dev")) < 0)        return -1;
    cdev_init(&my_cdev, &fops);    my_cdev.owner = THIS_MODULE;    my_cdev.ops = &fops;
    if ((cdev_add(&my_cdev, dev, 1)) < 0)        goto r_class;
    if (IS_ERR(dev_class = class_create(THIS_MODULE, "my_class")))        goto r_class;
    if (IS_ERR(device_create(dev_class, NULL, dev, NULL, "my_device")))        goto r_device;
    init_waitqueue_head(&my_waitqueue);
    if ((wait_thread = kthread_create(wait_function, NULL, "WaitThread")))        wake_up_process(wait_thread);
    return 0;
r_device:    class_destroy(dev_class);r_class:    unregister_chrdev_region(dev, 1);    return -1;
}
static void __exit my_driver_exit(void){    waitqueue_flag = 2;    wake_up_interruptible(&my_waitqueue);    device_destroy(dev_class, dev);    class_destroy(dev_class);    cdev_del(&my_cdev);    unregister_chrdev_region(dev, 1);}
module_init(my_driver_init);module_exit(my_driver_exit);
MODULE_LICENSE("GPL");MODULE_AUTHOR("feifei <feifei@gmail.com>");MODULE_DESCRIPTION("Simple linux driver");MODULE_VERSION("1.7");

编译运行演示如下:

                

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/734008.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安装jfrog container registry(jcr)

1、下载软件 下载地址,本案例下载的是jfrog-artifactory-jcr-7.59.11-linux.tar.gz: https://releases.jfrog.io/artifactory/bintray-artifactory/org/artifactory/jcr/jfrog-artifactory-jcr/ 2、解压下载下来的压缩包 tar zxf jfrog-artifactory-jcr-7.59.11-linux.tar…

双向滑动选择器

插件地址:https://ext.dcloud.net.cn/plugin?id3940 注意: 当改变值是,让滑块自动滑动需要调用: this.$refs.powerSlider.updateValue(that.tempPowerValue[0], that.tempPowerValue[1], false); <view style"width: 90%;margin: 15px"><cj-slider ref…

ffmpeg音视频开发从入门到精通——ffmpeg 视频数据抽取

文章目录 FFmpeg视频处理工具使用总结环境配置主函数与参数处理打开输入文件获取流信息分配输出文件上下文猜测输出文件格式创建视频流并设置参数打开输出文件并写入头信息读取、转换并写入帧数据写入尾信息并释放资源运行程序注意事项源代码 FFmpeg视频处理工具使用总结 环境…

tp5学习基本控制器和视图

1 文件结构 正在上传…重新上传取消 application 主要操作目录 extend 扩展 public 入口文件 runtime 运行时文件 thinkphp 核心代码 vendor 三方扩展 2 public/index.php 解析 正在上传…重新上传取消 .htaccess Apache 可写文件 index.php 主目录 router.php 路由文件 3 inde…

LLC开关电源开发:第四节,LLC软件设计报告

LLC源代码链接 数控全桥LLC开发板软件设计报告  1. LLC硬件及软件框架2. LLC软件设计2.1 工程文件说明2.2 LLC中断设计2.2.1 20us中断2.2.2 5ms中断 2.3 LLC状态机设计2.3.1 初始化状态2.3.2 空闲状态2.3.3 软启动状态2.3.4 正常运行状态2.3.5 故障状态 2.4 环路设计2.4.1 环路…

YOLOv8中的C2f模块

文章目录 一、结构概述二、模块功能 一、结构概述 C2f块:首先由一个卷积块(Conv)组成&#xff0c;该卷积块接收输入特征图并生成中间特征图特征图拆分:生成的中间特征图被拆分成两部分&#xff0c;一部分直接传递到最终的Concat块&#xff0c;另一部分传递到多个Botleneck块进…

three.js 第八节 - gltf加载器、解码器

// ts-nocheck // 引入three.js import * as THREE from three // 导入轨道控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls // 导入hdr加载器&#xff08;专门加载hdr的&#xff09; import { RGBELoader } from three/examples/jsm/loaders…

Unit redis-server.service could not be found.

我的报错如下Unit redis-server.service could not be found. 关键是刷新后台服务 sudo systemctl daemon-reload启动redis-server sudo systemctl start redis-server查看redis-Server服务状态 sudo systemctl status redis-server

【JUC并发编程】

Java并发常见面试题总结&#xff08;上&#xff09; 线程 什么是线程和进程? 何为进程? 进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。系统运行一个程序即是一个进程从创建&#xff0c;运行到消亡的过程。 在 Java 中&am…

Zigbee协议详解:低功耗无线通信的理想选择

什么是Zigbee协议 Zigbee是一种基于IEEE 802.15.4标准的无线通信协议&#xff0c;专为低功耗、低数据速率和短距离通信设计。它广泛应用于物联网&#xff08;IoT&#xff09;设备&#xff0c;如智能家居、工业自动化和健康监测等领域。Zigbee协议由Zigbee联盟维护和推广&#x…

[Redis]持久化机制

众所周知&#xff0c;Redis是内存数据库&#xff0c;也就是把数据存在内存上&#xff0c;读写速度很快&#xff0c;但是&#xff0c;内存的数据容易丢失&#xff0c;为了数据的持久性&#xff0c;还得把数据存储到硬盘上 也就是说&#xff0c;内存有一份数据&#xff0c;硬盘也…

【iOS】编译二进制文件说明

编译二进制文件说明 如何生成文件路径文件说明第一部分&#xff1a;.o文件第二部分&#xff1a;link第三部分&#xff1a;Segment第四部分&#xff1a;Symbol 如何生成 使用Xcode进行编译 &#xff0c;会生成二进制相关文件&#xff0c;可以更详细看产物的布局 项目Target -&…

使用粒子滤波(particle filter)进行视频目标跟踪

虽然有许多用于目标跟踪的算法&#xff0c;包括较新的基于深度学习的算法&#xff0c;但对于这项任务&#xff0c;粒子滤波仍然是一个有趣的算法。所以在这篇文章中&#xff0c;我们将介绍视频中的目标跟踪&#xff1a;预测下一帧中物体的位置。在粒子滤波以及许多其他经典跟踪…

容器之布局容器的演示

代码; #include <gtk-2.0/gtk/gtk.h> #include <glib-2.0/glib.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <stdio.h>void change_image(GtkFileChooserButton *filebutton, // GdkEvent *event,GtkImage *image) {gtk_image_set_from_file(im…

Vue3 - 在项目中使用vue-i18n不生效的问题

检查和配置 Vue I18n 确保你已经正确安装了Vue I18n并且配置了组合API模式。 安装 Vue I18n npm install vue-i18nnext配置 i18n.js import { createI18n } from vue-i18n; import messages from ./messages;const i18n createI18n({legacy: false, // 使用组合 API 模式l…

DC-DC 高压降压、非隔离AC-DC、提供强大的动力,选择优质电源芯片-(昱灿)

畅享长续航&#xff0c;尽在我们的充电芯片&#xff01; 无论是手机、平板还是智能设备&#xff0c;长时间使用后电量不足总是令人头疼。然而&#xff0c;我们的充电芯片将为您带来全新的充电体验&#xff01;采用先进的技术&#xff0c;我们的充电芯片能够提供快速而稳定的充电…

逻辑地址 线性地址 物理地址 Linux kernel 内存管理设计

linux kernel 2.6以后的MM&#xff0c;受到了兼容 risc arch cpu 的 MM 的启发&#xff0c;新的 MM 架构对 x86 上任务切换的效率上也有明显提高。 新的MM架构&#xff0c;GDT 不再随着进程的创建与结束而创建和删除 新的表项。 TSS段 也只有一个&#xff0c;进程切换时&…

upload-labs实验过程中遇到的问题

第6题问题&#xff1a;500异常码 发现500异常码&#xff0c;这个应该是apache版本问题&#xff0c;可更换其他版本&#xff0c;或者更换为nginx 12题问题&#xff1a;上传出错 出现上传错误&#xff0c;大概率是php版本问题&#xff0c;需要下载php5.2.17版本的php或者更换其他…

华为云下Ubuntu20.04中Docker的部署

我想用Docker拉取splash&#xff0c;Docker目前已经无法使用&#xff08;镜像都在国外&#xff09;。这导致了 docker pull 命令的失败&#xff0c;原因是timeout。所以我们有必要将docker的源设置在国内&#xff0c;直接用国内的镜像。 1.在华为云下的Ubuntu20.04因为源的原因…

使用Spring Boot实现用户认证和授权

文章目录 引言第一章 Spring Boot概述1.1 什么是Spring Boot1.2 Spring Boot的主要特性 第二章 用户认证和授权基础知识2.1 用户认证2.2 用户授权2.3 Spring Security概述 第三章 项目初始化第四章 实现用户认证和授权4.1 定义用户实体类和角色实体类4.2 创建Repository接口4.3…