我们在开发或调试设备驱动时常常用到/sys目录下的东西,甚至有的时候完全依赖这个目录下的东东,而不用/dev下的设备,比如一些传感器,vibrator,leds等。安卓驱动的HAL层大量使用了这个/sys下的属性节点。那么这个/sys目录下的是干什么的呢?为什么要这个目录?原来的/proc目录下比较混乱,后来将与设备相关的都放到/sys下。
它的出现是用于解决linux2.6之前的以下问题
#没有统一的机制表达驱动程序和设备的关系。
#不存在一般的热插拔(hotplug)机制。
#procfs 文件系统过度混乱,包含了许多不是进程(process)的信息。
其实这是个虚拟文件系统,用于导出内核对象(kobject),动态的生成的,与/proc类似,没有实际的存放介质,它一开始是一ramfs为基础的,断电就没有了,内存中。这个文件系统不仅可以把设备(devices)和驱动程序(drivers) 的信息从内核输出到 用户空间,也可以用来对设备和驱动程序做设置。用户可以在用户空间操作sysfs节点以达到修改设备驱动属性值,甚至达到/dev下的read,write,ioctl等的操作。/sys目录会将设备以层次结构的方式呈现,你经常会看到/sys/class/下有input,rtc,block等分类,也能看到/sys/bus/下有spi,iic等总线类别。
总之,sysfs是内核空间和用户空间的沟通手段,可以将设备驱动信息给你用户空间看,还能让你操作设备驱动。
sysfs文件系统中提供了四类文件的创建与管理,分别是目录、普通文件、软链接文件、二进制文件。目录层次往往代表着设备驱动模型的结构,软链接文件则代表着不同部分间的关系。比如某个设备的目录只出现在/sys/devices下,其它地方涉及到它时只好用软链接文件链接过去,保持了设备唯一的实例。而普通文件和二进制文件往往代表了设备的属性,读写这些文件需要调用相应的属性读写。这个过程跟kobject联系在一起,就像基类一样,每一个sysfs文件都有一个kobject,以kobject.parent建立层次关系,所以kobject也很重要,要一起看了。
先看下linux/sysfs.h
struct attribute { const char *name; umode_t mode;};
struct attribute_group { const char *name; umode_t (*is_visible)(struct kobject *, struct attribute *, int); struct attribute **attrs;};
//struct attribute_group创建一组节点,由sysfs_create_group()创建
/** * Use these macros to make defining attributes easier. See include/linux/device.h * for examples.. */#define __ATTR(_name,_mode,_show,_store) { .attr = {.name = __stringify(_name), .mode = _mode }, .show = _show, .store = _store, }#define __ATTR_RO(_name) { .attr = { .name = __stringify(_name), .mode = 0444 }, .show = _name##_show, }#define __ATTR_NULL { .attr = { .name = NULL } }#define attr_name(_attr) (_attr).attr.name
struct bin_attribute { struct attribute attr; size_t size; void *private; ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *, char *, loff_t, size_t); ssize_t (*write)(struct file *,struct kobject *, struct bin_attribute *, char *, loff_t, size_t); int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr, struct vm_area_struct *vma);};struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); const void *(*namespace)(struct kobject *, const struct attribute *);};
释放:
//kobj为kobject_create_and_add()函数的返回值
void kobject_put(struct kobject *kobj)
联系客服