精华内容
下载资源
问答
  • 一、以led灯 的android 系统架构作为实例 开门见山,我们知道在Android operation system 的四层架构;见右图   其中HAL层以下,即kernel层运行在system space,HAL-》framework一直以上运行在user space。 HAL ...

    做为专业工程师,对自我基本要求:从事的工作必定不能丝毫马虎。

    一、以led灯 的android 系统架构作为实例

    开门见山,我们知道在Android operation system 的四层架构;见右图

     


    其中HAL层以下,即kernel层运行在system space,HAL-》framework一直以上运行在user space。

    HAL (Hardware abstract layout)就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。

    二、HAL层对驱动层的调用最终都是通过对给出的设备节点操作

     上层对驱动的操作通常为file operation read & write 读写操作《=对应于函数show & store==》

    static int
    write_int(char const* path, int value)
    {
        int fd;
        static int already_warned = 0;
    
        ALOGD("entry write_int path = %s, value=%d\n", path,value);
        
        fd = open(path, O_RDWR);
        if (fd >= 0) {
    
        ALOGD("entry write_int_open fd=%d\n", fd);
            char buffer[20];
            int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
            ssize_t amt = write(fd, buffer, (size_t)bytes);
            
    	close(fd);
            return amt == -1 ? -errno : 0;
        } else {
            if (already_warned == 0) {
                ALOGE("write_int failed to open %s\n", path);
                already_warned = 1;
            }
            return -errno;
        }
    }
    其中path 变量即为sysfs 下的文件路径;

    char const*const RED_LED_FILE
            = "/sys/class/leds/red/brightness";
    

    而write函数对 RED_LED_FILE文件的操作实际上是调用了static ssize_t brightness_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t size)函数;(至于为什么,怎么来的后续分析)

    来看下函数brightness_store();在led-class.c文件中

    static ssize_t brightness_store(struct device *dev,
    		struct device_attribute *attr, const char *buf, size_t size)
    {
    	struct led_classdev *led_cdev = dev_get_drvdata(dev);
    	unsigned long state;
    	ssize_t ret;
    
    	mutex_lock(&led_cdev->led_access);
    
    	if (led_sysfs_is_disabled(led_cdev)) {
    		ret = -EBUSY;
    		goto unlock;
    	}
    
    	ret = kstrtoul(buf, 10, &state);
    	if (ret)
    		goto unlock;
    
    	led_cdev->usr_brightness_req = state;
    	__led_set_brightness(led_cdev, state);
    
    	ret = size;
    unlock:
    	mutex_unlock(&led_cdev->led_access);
    	return ret;
    }
    继续往下走——~! 你所见到的,都是有根据和原因的,只是没有找打代码对应的地方而已。

    最后函数在进行容错判断(增强程序健壮性)之后,实际上执行的是led_cdev->brightness_set(led_cdev,value)

    对一些重要的数据结构要了解:一般数据结构都是对被模拟的object进行抽象,struct led_classdev代表的意思是led灯类的设备;

    	enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
    

    看下代码:这里brightness_set是函数指针类型(有点类似面向对象语言中的虚函数、抽象函数的概念),它的定义根据不同的指向的函数来实现;我Kconfig配置使用xxled.C文件在probe()函数下将该函数指向

    		INIT_WORK(&led->brightness_work, aw2013_brightness_work);
    		printk("zhufeng: aw2013 INIT_WORK end\n");
    
    		led->cdev.brightness_set = aw2013_set_brightness;
    
    		rc = led_classdev_register(&led->client->dev, &led->cdev);
    		if (rc) {
    			dev_err(&led->client->dev,
    				"unable to register led %d,rc=%d\n",
    				led->id, rc);
    			goto free_pdata;
    		}
    所以最终实现在函数aw2013_set_brightness()当中;每个平台不同,具体的实现细节会不同,
     唤醒工作队列schedule_work(&led->brightness_work);在aw2013_brightness_work()中真正实现。

    三、adb调试下的异曲同工

    上面所述的上层代码流程通过对设备节点操作;adb(android debug bridge)调试也是一样;




    四、小结

           本文主要讲述的是:以led 驱动为例从用户空间的HAL层,通过对设备节点的操作,走到kernel 空间,通过对属性文件的读写操作,操作相应的硬件。

    那么问题来了:这些属性文件提供了什么机制,小透露;通过向sysfs 系统中注册到特定的目录下,为上层提供服务(直白些被上层调用)。见整理二。







    展开全文
  • 一)linux文件系统目录结构介绍进入Linux根目录/之后,运行:ls -l 即可查看。/bin:包含基本命令文件,如ls,cp等,这个文件中的文件都是可执行的。/boot:Linux系统的内核及引导系统程序所需要的文件,如vmlinuz,...

    一)linux文件系统目录结构介绍

    进入Linux根目录/之后,运行:ls -l 即可查看。

    /bin:包含基本命令文件,如ls,cp等,这个文件中的文件都是可执行的。

    /boot:Linux系统的内核及引导系统程序所需要的文件,如vmlinuz,initrd.img都位于这个目录中。

    /dev:设备文件存储目录,应用程序通过对这些文件的读写和控制就可以访问实际的设备。如:ls -l /dev。

    /etc:系统配置文件的所在地,一些服务器的配置文件也在这里,如帐号名跟密码。

    /home:普通用户的家目录。

    /lib:库文件的存放目录。

    /lost+found:在EXT2和EXT3文件系统中,系统崩溃时的一些文件碎片存放在这里。

    /mnt:一般是用来存放挂载储存设备的挂载目录的,比如cdrom的目录。有时我们可以把让系统开机自动挂载文件系统,把挂载点放在这里 也是可以的。

    /opt:有些软件包会安装在这里,比如open office或者用户自己编译的软件包也可以安装在这个目录中。

    /proc:操作系统运行时,进程及内核信息(如CPU,内存)存放在这里。它是个伪文件系统目录,仅存在于内存中。

    /root:超级用户的根目录。

    /sbin:超级用户的命令文件存放的目录。

    /tmp:用来存放系统运行时产生的临时文件。

    /usr:系统存放程序的目录,内核发行版提供的软件包大多数被安装在这里。

    /var:这个目录的内容经常变动,如/var/log用来存放系统日志。

    /sys:Linux 2.6内核支持的sysfs文件系统被映射在此目录。Linux

    设备驱动模型中的总线、驱动和设备都可以在sysfs文件系统找到对应的节点。当内核检测到系统中出现了新设备后,内核会在sysfs文件系统中为该新设

    备生成一项新的记录。

    二)

    linux下有专门的文件系统用来对设备进行管理,devfs和sysfs就是其中两种。

    1,devfs:devfs是在2.4内核就出现了,它是用来解决linux中设备管理混乱的问题,linux内核开发人员开发了devfs。

    2,sysfs:是Linux

    内核中设计较新的一种虚拟的基于内存的文件系统,并没有一个实际存放文件的介质,断电后就玩完了。它的作用与proc

    有些类似,但除了与proc 相同的具有查看和设定内核参数功能之外,还有为Linux 统一设备模型作为管理之用。

    sysfs 文件系统总是被挂载在/sys

    挂载点上,sysfs的信息来源是kobject层次结构,读一个sysfs文件,就是动态的从kobject结构提取信息,生成文件。虽然在较早期的

    2.6内核系统上并没有规定sysfs的标准挂载位置,可以把sysfs 挂载在任何位置,但较近的2.6内核修正了这一规则,要求sysfs

    总是挂载在/sys目录上。sysfs 与proc 相比有很多优点:sysfs 的设计原则是一个属性文件只做一件事情,sysfs

    属性文件一般只有一个值,直接读取或写入。新设计的内核机制应该尽量使用sysfs机制,而将proc

    保留给纯净的“进程文件系统”。

    UBUNTU中比如:执行ls -F /sys,得block/ bus/ class/ dev/ devices/ firmware/ fs/ kernel/ module/ power/

    下面对/sys 文件系统下的目录结构做说明:

    /sys/devices:这是内核对系统中所有设备的分层次表达模型,也是 /sys 文件系统管理设备的最重要的目录结构;

    /sys/dev:这个目录下维护一个按字符设备和块设备的主次号码(major:minor)链接到真实的设备(/sys/devices下)的

    符号链接文件,它是在内核2.6.26 首次引入;

    /sys/bus:这是内核设备按总线类型分层放置的目录结构,devices中的所有设备都是连接于某种总线之下,在这里的每一种具体总线之下可

    以找到每一个具体设备的符号链接,它也是构成 Linux 统一设备模型的一部分;

    /sys/class:这是按照设备功能分类的设备模型,如系统所有输入设备都会出现在 /sys/class/input

    之下,而不论它们是以何种总线连接到系统。它也是构成Linux 统一设备模型的一部分;比如LED灯设备:cat

    /sys/class/leds/lcd-backlight/,终端回显:

    -rw-r--r--

    root root 4096 1970-01-01 00:00 uevent

    lrwxrwxrwx

    root root 1970-01-01 00:03 subsystem -> ../../leds

    lrwxrwxrwx

    root root 1970-01-01 00:03 device ->

    ../../../devices/platform/smdk-backlight

    drwxr-xr-x

    root root 1970-01-01 00:00 power

    -rw-r--r--

    system system 4096 1970-01-01 00:00 brightness

    其中device有指向smdk-backlight的符号链接,当你进入该目录再退回上层目录时,你会发现处于/sys/devices目录下,

    更说明了设备模型虽然采用不同方式却指向同一设备的概念。

    /sys/block:这里是系统中当前所有的块设备所在,按照功能来说放置在/sys/class

    之下会更合适,但只是由于历史遗留因素而一直存在于/sys/block, 但从2.6.22

    开始就已标记为过时,只有在打开了CONFIG_SYSFS_DEPRECATED 配置下编译才会有这个目录的存在,并且在2.6.26

    内核中已正式移到 /sys/class/block, 旧的接口/sys/block

    为了向后兼容保留存在,但其中的内容已经变为指向它们在/sys/devices/ 中真实设备的符号链接文件;

    /sys/firmware:这里是系统加载固件机制的对用户空间的接口,关于固件有专用于固件加载的一套API;

    /sys/fs:这里按照设计是用于描述系统中所有文件系统,包括文件系统本身和按文件系统分类存放的已挂载点,但目前只有fuse,gfs2

    等少数文件系统支持sysfs接口,一些传统的虚拟文件系统(VFS)层次控制参数仍然在sysctl (/proc/sys/fs)

    接口中;

    /sys/kernel:这里是内核所有可调整参数的位置,目前只有uevent_helper, kexec_loaded,

    mm,和新式的slab 分配器等几项较新的设计在使用它,其它内核可调整参数仍然位于sysctl (/proc/sys/kernel)

    接口中;

    /sys/module:这里有系统中所有模块的信息,不论这些模块是以内联(inlined)方式编译到内核映像文件(vmlinuz)中还是编

    译为外部模块(ko文件),都可能会出现在 /sys/module 中;

    /sys/power:这里是系统中电源选项,这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机、重

    启等。

    驱动跟内核接口分类如下:

    类型 所包含的内容 对应内核数据结构 对应/sys项

    设备(Devices) 设备是此模型中最基本的类型 struct

    device /sys/devices.../

    设备驱动(Device Drivers)

    多个相同设备只需要一份驱动程序 struct

    device_driver /sys/bus/pci/drivers

    设备类别(Device Classes)

    按照功能进行分类组织的设备层次树 /sys/class/input/ 下 struct class

    sysfs 给应用程序提供了统一访问设备的接口,但可以看到, sysfs 仅仅是提供了一个可以统一访问设备的框架,但究竟是否支持

    sysfs 还需要各设备驱动程序的编程支持;在 2.6 内核诞生 5年以来的发展中,很多子系统、设备驱动程序逐渐转向了 sysfs

    作为与用户空间友好的接口,但仍然也存在大量的代码还在使用旧的 proc 或虚拟字符设备的 ioctl 方式。

    展开全文
  •  sysfs是在内存中存在文件系统,它的文件都只在内存中存在。因此 对文件的读写实际是对内存的读写,不涉及对硬盘的操作   4.3.1 读文件的过程的分析  a  a 申请内存页函数: fastcall unsigned long...

    4.3     sysfs文件的读写

            sysfs是在内存中存在文件系统,它的文件都只在内存中存在。因此 对文件的读写实际是对内存的读写,不涉及对硬盘的操作
            

    4.3.1 读文件的过程的分析

            a
            a

    申请内存页函数:

    fastcall unsigned long get_zeroed_page(gfp_t gfp_mask)
    {
    	struct page * page;
    
    	/*
    	 * get_zeroed_page() returns a 32-bit address, which cannot represent
    	 * a highmem page
    	 */
    	BUG_ON((gfp_mask & __GFP_HIGHMEM) != 0);
    
    	page = alloc_pages(gfp_mask | __GFP_ZERO, 0);
    	if (page)
    		return (unsigned long) page_address(page);
    	return 0;
    }

    分配页面空间函数 alloc_pages:

    #ifdef CONFIG_NUMA
    extern struct page *alloc_pages_current(gfp_t gfp_mask, unsigned order);
    
    static inline struct page *
    alloc_pages(gfp_t gfp_mask, unsigned int order)
    {
    	if (unlikely(order >= MAX_ORDER))
    		return NULL;
    
    	return alloc_pages_current(gfp_mask, order);
    }
    extern struct page *alloc_page_vma(gfp_t gfp_mask,
    			struct vm_area_struct *vma, unsigned long addr);
    #else
    #define alloc_pages(gfp_mask, order) \
    		alloc_pages_node(numa_node_id(), gfp_mask, order)
    #define alloc_page_vma(gfp_mask, vma, addr) alloc_pages(gfp_mask, 0)
    #endif

    mm/Mempolicy.h :

    /**
     * 	alloc_pages_current - Allocate pages.
     *
     *	@gfp:
     *		%GFP_USER   user allocation,
     *      	%GFP_KERNEL kernel allocation,
     *      	%GFP_HIGHMEM highmem allocation,
     *      	%GFP_FS     don't call back into a file system.
     *      	%GFP_ATOMIC don't sleep.
     *	@order: Power of two of allocation size in pages. 0 is a single page.
     *
     *	Allocate a page from the kernel page pool.  When not in
     *	interrupt context and apply the current process NUMA policy.
     *	Returns NULL when no page can be allocated.
     *
     *	Don't call cpuset_update_task_memory_state() unless
     *	1) it's ok to take cpuset_sem (can WAIT), and
     *	2) allocating for current task (not interrupt).
     */
    struct page *alloc_pages_current(gfp_t gfp, unsigned order)
    {
    	struct mempolicy *pol = current->mempolicy;
    
    	if ((gfp & __GFP_WAIT) && !in_interrupt())
    		cpuset_update_task_memory_state();
    	if (!pol || in_interrupt())
    		pol = &default_policy;
    	if (pol->policy == MPOL_INTERLEAVE)
    		return alloc_page_interleave(gfp, order, interleave_nodes(pol));
    	return __alloc_pages(gfp, order, zonelist_policy(gfp, pol));
    }
    EXPORT_SYMBOL(alloc_pages_current);

    include/linux/Gfp.h

    static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
    						unsigned int order)
    {
    	if (unlikely(order >= MAX_ORDER))
    		return NULL;
    
    	/* Unknown node is current node */
    	if (nid < 0)
    		nid = numa_node_id();
    
    	return __alloc_pages(gfp_mask, order,
    		NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_mask));
    }

    a

    4.3.2 写文件的过程分析

            普通文件的写函数是sysfs_write_file,它的代码如下:


            a

    展开全文
  • linux sysfs文件系统(一)概述

    千次阅读 2019-09-30 21:40:40
    简单的说,sysfs是一个基于内存的文件系统,它的作用是将内核信息以文件的方式提供给用户程序使用。 sysfs可以看成与proc,devfs和devpty同类别的文件系统,该文件系统是虚拟的文件系统,可以更方便对系统设备进行...

    简单的说,sysfs是一个基于内存的文件系统,它的作用是将内核信息以文件的方式提供给用户程序使用。

           sysfs可以看成与proc,devfs和devpty同类别的文件系统,该文件系统是虚拟的文件系统,可以更方便对系统设备进行管理。它可以产生一个包含所有系统硬件层次视图,与提供进程和状态信息的proc文件系统十分类似。

           sysfs把连接在系统上的设备和总线组织成为一个分级的文件,它们可以由用户空间存取,向用户空间导出内核的数据结构以及它们的属性。sysfs的一个目的就是展示设备驱动模型中各组件的层次关系,其顶级目录包括block,bus,drivers,class,power和firmware等.

           sysfs提供一种机制,使得可以显式的描述内核对象、对象属性及对象间关系。sysfs有两组接口,一组针对内核,用于将设备映射到文件系统中,另一组针对用户程序,用于读取或操作这些设备。下面描述了内核中的sysfs要素及其在用户空间的表现:

    sysfs在内核中的组成要素在用户空间的显示
    内核对象(kobject)目录
    对象属性(attribute)文件
    对象关系(relationship)链接(Symbolic Link)

    sysfs核心负责为内核中的内部表示和用户空间的外部呈现建立对应关系

    1 内核对象被映射为用户空间的目录;

    2 对象属性被映射为用户空间的常规文件

    3 对象关系被映射为用户空间的符号链接

    sysfs代码在fs/sysfs中,他提供两种构件,也就是两个方面的API,一是内核编程接口,用于向内核其他模块提供构建内部树的API,另一是文件系统接口,使得用户空间可以查看并操作对应的内核对象

    构建内核对象,对象属性和对象关系

    sysfs内部树中有4种类型的节点:目录节点,链接节点,属性节点和二进制属性节点,分别对应内核对象,对象关系,对象属性,内部树的所有节点都是用sysfs_dirent描述符表示,根保存在全局变量sysfs_root中。

    每个目录节点都对应一个kobject结构,而属性节点则会包含attribute结构,没有kobject结构。


    内核对象

    数据结构为kobject,在内部用一个目录节点表示,由sysfs文件系统作为目录输出到用户空间,由于是目录节点,他下面将会创建其他的节点(链接节点,属性节点,二进制节点)。表示目录节点的数据结构是sysfs_elem_dir,其children域指向他第一个孩子节点,沿着孩子节点的s_sibling组成一个链表。

     sysfs_dirent

    sysfs_dirent是组成sysfs单元的基本数据结构,它是sysfs文件夹或文件在内存中的代表。sysfs_dirent只表示文件类型(文件夹/普通文件/二进制文件/链接文件)及层级关系,其它信息都保存在对应的inode中。我们创建或删除一个sysfs文件或文件夹事实上只是对以sysfs_dirent为节点的树的节点的添加或删除。
     

    相互关系
      创建文件即是在kobject对应的目录下增加属性文件。
      创建bin文件即是在kobject对应的目录下增加bin属性文件。
      创建链接是创建一个连接指向对应的kobject创建的目录.
      创建属性组即首先创建一个目录,然后在该目录内依次添加所有属性文件
      并且这些创建都需要在kobject注册之后使用/inlude/linux/sysfs.h中定义的接口函数和kobject进行添加。

    引用网友的一个结构图:

     

     

    展开全文
  • (1)linux文件系统目录结构介绍  进入Linux根目录/之后,运行:ls -l 即可查看。 /bin:包含基本命令文件,如ls,cp等,这个文件中的文件都是可执行的。 /boot:Linux系统的内核及引导系统程序所需要的文件,如...
  • 4.2 sysfs文件的打开操作 4.2.1 real_lookup函数详解  a 4.2.2 为文件创建inode结构 4.2.3 为dentry结构绑定属性 4.2.4 调用文件系统的open函数
  • 对于一位专业的工程师而言:自己所属的工作不能存在丝毫马虎 ...这里需要sysfs 虚拟文件系统相关的背景知识,最好去了解sysfs 的机制与理论知识,本文尽量不牵扯太多。 一、什么是属性?什么是Kobject?  
  • sysfs 文件系统

    2021-05-10 01:08:08
    Sysfs 是Linux 2.6所提供的一种虚拟文件系统。这个文件系统不仅可以把设备(devices)和驱动程序(drivers)的信息从内核输出到用户空间,也可以用来对设备和驱动程序做设置。一、初识sys 文件系统简单的说,sysfs是一个...
  • 4.1 文件和目录的创建 4.1.1 sysfs文件系统的初始化 4.1.2 sysfs文件系统目录的创建 4.1.3 普通文件的创建
  • sysfs文件系统

    2013-05-31 10:58:34
    sysfs文件系统
  • sysfs是一个内存虚拟文件系统,提供了一个kobject层次结构的视图。sysfs根目录下包含至少10个目录: l block:该目录包含了系统中注册的每个块设备对应的目录。这些目录中包含了块设备的任何分区。 l bus:该目录...
  • 一、Sysfs文件系统 内核设备模型主要的模块和用户之间能看到的相关部分就是sysfs文件系统了。内核在启动的时候会注册sysfs文件系统,并且在启动系统的初期。通过mount命令挂载sysfs文件系统到/sys挂载点。 Mount -t ...
  • Linux文件系统sysfs

    2021-05-10 01:09:05
    上图表示的是一个kobject的层次结构.dentry的d_fsdata字段指定该结点所表示的sysfs_dirent.sysfs_dirent.s_parent表示它的父kobject. sysfs_dirent.s_sibling表示它的兄弟结点. sysfs_dirent.s_dir.children表示它...
  • Linux中sysfs文件系统

    2020-10-18 21:50:52
    sysfs文件系统 sysfs文件系统和proc文件系统也是内存型文件系统 sysfs被加载在/sys/目录下,它的子目录包括如下: ├── block ├── bus ├── class ├── dev ├── devices ├── firmware ├── fs ├...
  • 文章主要介绍了一些设备驱动相关的sys文件系统,结合ldd3(linux device driver 3)中的示例代码(主要是lddbus 和sculld 文件夹),详细分析虚拟文件系统sysfs,以及如何编写基于sysfs的模块化的驱动程序。使用的内核是...
  • 二、sysfs系统 1.基础简介  sysfs是Linux 2.6所提供的一种虚拟档案系统。这个档案系统不仅可以把装置(devices)和驱动程式(drivers)的资讯从kernel space输出到user space,也可以用来对装置和驱动程式做设定。  ...
  • sysfs和proc文件系统解析

    千次阅读 2019-07-02 22:01:52
    1.1)Linux设备驱动模型中的总线、驱动和设备都可以在sysfs文件系统中找到对应的节点。当内核检测到在系统中出现了新设备后,内核会在sysfs文件系统中生成一项新的记录它会产生一个包括所有系统硬件的层级视图。 ...
  • 上面的文章分析了sysfs文件的创建过程,既然文件已经建立起来了,读写它才是我们最终的目的撒,本文就来看看sysfs是咋个通过VFS接口读写sysfs下的文件.sysfs属性文件操作方法在函数sysfs_init_inode()中初始化了sysfs...
  • 前面分别分析了devtmpfs、sockfs,本次开始分析sysfs文件系统,该文件系统与设备驱动模型是结合使用的。因此在介绍该文件系统的同时,也需要说明linux的设备驱动程序模型。 本次sysfs文件系统分析主要涉及如下几...
  • sysfs文件系统详解IBM

    2012-03-15 18:49:23
    sysfs 文件系统详解,IBM官方网站学习,
  • 在/sysfs文件系统中添加和删除文件

    千次阅读 2016-11-23 20:42:11
    在Linux-2.6.18内核中编写一个内核模块,其功能是在/sysfs文件系统中增加一个目录hello,并在这个目录中增加一个文件world,文件的内容为hello world。 代码附录在博文的末尾 1. 在/目录中新建一个目录test,在...
  • 1 前言内核中有三个常用的伪文件系统:procfs,debugfs和sysfs。procfs — The proc filesystem is a pseudo-filesystem which provides an interface to kernel data structures. sysfs — The filesystem for ...
  • Sysfs是 Linux 2.6 所提供的一种虚拟文件系统。这个文件系统不仅可以把设备(devices)和驱动程序(drivers) 的信息从内核输出到用户空间,也可以用来对设备和驱动程序做设置。[编辑]历史Linux内核开发团队在 Linux 2.5...
  • sysfs文件系统学习  sysfs 是一种基于 ram 的文件系统,它提供了一种用于向用户空间展现内核空间里的对象、属性和链接。 sysfs 与 kobject 层次紧密相连,它将 kobject 层次关系表现出来,使得用户空间可以看见...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,376
精华内容 13,750
关键字:

文件系统sysfs