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

2024-06-21 21:44

本文主要是介绍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");

编译运行演示如下:

                

这篇关于Linux开发讲课7---Linux sysfs文件系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082414

相关文章

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Linux命令之firewalld的用法

《Linux命令之firewalld的用法》:本文主要介绍Linux命令之firewalld的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux命令之firewalld1、程序包2、启动firewalld3、配置文件4、firewalld规则定义的九大

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S