zoukankan      html  css  js  c++  java
  • Linux设备管理(五)_写自己的sysfs接口

    我们在Linux设备管理(一)_kobject, kset,ktype分析一文中介绍了kobject的相关知识,在Linux设备管理(二)_从cdev_add说起Linux设备管理(三)_总线设备的挂接举例介绍了内核中是如何进行设备管理的,并在Linux设备管理(四)_从sysfs回到ktype一文中结合sysfs机制和kobject对内核的设备管理机制进行一定深度的讨论,从中可以看出,字符设备的cdev本身的kobject是没有初始化的,也没有在sysfs中创建任何目录,平台设备是将设备挂接到总线上,在挂接的过程中就会在相应的sysfs目录创建相应的文件。在这里,本文将搭建一个sysfs模块接口的框架,此后,就可以为我们自己的驱动在sysfs中添加属性读写接口。

    准备属性和回调接口

    我们知道,呈现在sysfs中的文件名其实都是内核中ktype的属性值,而从用户空间对这些属性值进行读写其实就是回调了我们在ktype结构中注册读写函数,所以,这里我们准备了两个函数,值得注意的是,内核会将用户空间的buf转换到内核空间并当作参数传入回调函数,所以我们就不用再进行这个转换。这里由于没有实际的属性,我就只是打印一下信息,实际使用的时候这两个函数要对内核中的真实属性进行读写。

    static char kbuf[1024] = {0};
    static ssize_t my_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
    {
    	char info[]="my_show is called
    ";
    	return scnprintf(buf,sizeof(info),info);
    }
    
    static ssize_t my_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
    {
    	printk("%s is called
    ",__func__);
    	strncpy(kbuf,buf,count);
    	printk("user_buf:%s,count:%ld|after copy,kbuf:%s
    ",buf,count,kbuf);
    	return count;
    }
    

    构造kobj_attribute

    准备好了原材料,第一道工序就是将属性和回调接口封装到一个kobj_attribute结构对象中,当然对这个属性的读写权限等信息也应该进行封装,我们来回顾一下这个结构

    //linux/kobject.h
    139 struct kobj_attribute {  
    140         struct attribute attr;
    141         ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
    142                         char *buf);
    143         ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
    144                          const char *buf, size_t count);
    145 };
    
    //linux/sysfs.h
     29 struct attribute { 
     30         const char              *name;
     31         umode_t                 mode;   //权限
     32         ...
     37 };
    

    当然,内核也给我们提供了相应的宏来快速的构造这个结构

    //linux/sysfs.h
    100 #define __ATTR(_name, _mode, _show, _store) {                           
    101         .attr = {.name = __stringify(_name),                            
    102                  .mode = VERIFY_OCTAL_PERMISSIONS(_mode) },             
    103         .show   = _show,                                                
    104         .store  = _store,                                               
    105 }   
    

    使用了这个宏,我们就可以快速的构造我们的kobj_attribute结构

    //show是name,就是sys中的文件名
    static struct kobj_attribute my_sysfs_read =__ATTR(show, S_IRUSR, my_show, NULL);
    
    static struct kobj_attribute my_sysfs_write =__ATTR(write, S_IWUSR, NULL,my_store);
    

    构造attribute数组

    一个kobject网完对应多个attribute,此时就需要将这些attribute封装成一个结构体数组,注意这个数组最后一个元素一定要是NULL

    static struct attribute *my_sysfs_attr[] = {
    	&my_sysfs_read.attr,
    	&my_sysfs_write.attr,
    	NULL,
    };
    

    如果这些属性直接放到kobject的目录中,我们可以直接使用sysfs_create_file(),但通常情况下,我们更多的将上述的struct attribute进行进一步的封装,并使用sysfs_create_group()来创建一个名为attribute_group.name的、包含struct attribute中的属性目录,这种方式更加的灵活,因为如果我们不指定目录的名字,那么效果个sysfs_create_file()是一样的。

    static struct attribute_group my_sysfs_attr_group = {
    	.name = "sub_my_attr",		//不写这个成员就不会创建子文件夹
    	.attrs = my_sysfs_attr,
    };
    
    struct kobject *my_kobj = NULL;
    
    int mysys_init(void)
    {
        ...
    	my_kobj = kobject_create_and_add("my_sysfs", NULL);
    	sysfs_create_group(my_kobj, &my_sysfs_attr_group);
    	...
    }
    
    void mysys_exit(void)
    {
    	...
    	sysfs_remove_group(my_kobj, &my_sysfs_attr_group);
    	kobject_put(my_kobj);
    }
    

    输出

    将上述的程序编译成模块,我们就可以观察到下面的输出结果。

  • 相关阅读:
    直接选择排序(C++模版技术实现)
    求素数
    快速排序(C++模版技术实现)
    堆排序(C++模版技术实现)
    简单链式二叉树(C++模版技术实现)
    归并排序(C++模版技术实现)
    求斐波那契数列的两种解法
    C++中改变setw(n)的对齐方式
    C中的64位整型
    Windows版GCC之TDMGCC 4.5.2
  • 原文地址:https://www.cnblogs.com/xiaojiang1025/p/6227421.html
Copyright © 2011-2022 走看看