翻译sysfs.txt

sysfs是一个内存文件系统,他提供了内核与用户之间的数据属性和连接交互,sysfs与kobject联系紧密。


内核编译的时候要 CONFIG_SYSFS

 mount -t sysfs sysfs /sys 


每一个注册的kobject都有一个目录在sysfs,这个目录地址在kobj的父对象目录下,表征为层级,顶层目录表现为最高层级。


sysfs_dirent对象下面有一个指向kobj的指针,这个指针之前是用来作引用计数用的,现如今引用计数只被sysfs_schedule_callback()修改。


属性被当做普通文件形式暴露出来。可以通过普通文件io读写内核属性。


属性应该是asc码 txt文件,最好一个文件只有一个值,明显这种机制不够用,所以也允许多个值的情况。


struct attribute { char                    * name;
        struct module *owner;
        umode_t                 mode; 

};

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

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

一个光的属性不包含读写函数,子系统需要自己分装。

例如:

struct device_attribute { struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); 

ssize_t (*store)(struct device *dev, struct device_attribute *attr,

 const char *buf, size_t count);

 };


int device_create_file(struct device *, const struct device_attribute *); 

void device_remove_file(struct device *, const struct device_attribute *); 


It also defines this helper for defining device attributes: 
#define DEVICE_ATTR(_name, _mode, _show, _store) \ 

struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)


For example, declaring


static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo); 

static struct device_attribute dev_attr_foo = { .attr= { .name = "foo",
.mode = S_IWUSR | S_IRUGO,
.show = show_foo,
.store = store_foo, }, 

};


当子系统定义了一个新的属性类型,那他必须自己实现读写函数来调用打印和保存方法。

struct sysfs_ops { 

ssize_t (*show)(struct kobject *, struct attribute *, char *);
        ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);

 };


子系统必须先定义kobj_type用来保存sysfs_ops指针。


当文件被读或者写了,sysfs会调用正确的方法。


#define to_dev(obj) container_of(obj, struct device, kobj) 

#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { 

struct device_attribute *dev_attr = to_dev_attr(attr);
        struct device *dev = to_dev(kobj);
        ssize_t ret = -EIO;
        if (dev_attr->show) 

ret = dev_attr->show(dev, dev_attr, buf); 

if (ret >= (ssize_t)PAGE_SIZE) { 

print_symbol("dev_attr_show: %s returned bad count\n", (unsigned long)dev_attr->show); 

}
        return ret;

 } 


为了读写属性,show和store函数必须被赋值,函数类型需要要与设备属性的一样

ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); 

ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); 


sysfs申请一个页表来发送数据,每次读写只会调用一次底层函数,因此有如下的要求:

读的时候,show函数必须要填满整个buffer,回想一个属性只能传一个或者一组值,这样效率才不会太低。

这样允许用户空间 局部的读和seek整个文件,如果用户seek到0 或者pread 0 ,那么show函数会再次调用,充填buffer


写的时候,sysfs认为整个buffer都有内容,传递整个buffer到store函数

写的时候,先读出来,修改 在写回去

读写的buffer需要用同一个buffer


写会使得show刷新不管文件pos

buffer永远一个页表大小

show函数会返回buffer字符的数量 ,实现是靠scnprintf函数

store函数返回不超过一个页表大小数据,

读写会返回错误值


对象会被sysfs保存在内存中,实际对象是否存在不得而知。


A very simple (and naive) implementation of a device attribute is:
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name); }
static ssize_t store_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { snprintf(dev->name, sizeof(dev->name), "%.*s", (int)min(count, sizeof(dev->name) - 1), buf); return count; }
static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
(Note that the real implementation doesn't allow userspace to set the name for a device.) 


sysfs目录结构直接暴露了内核数据结构层级。

devices/ 表征设备树

bus/ bus类型 都有 

devices/   指向根目录下的设备目录
drivers/  包含 每个启动的驱动

dev/  包含 char 和 block 里面有 <major>:<minor>链接,指向设备目录,stat 命令就是用的这里


The following interface layers currently exist in sysfs:
- devices (include/linux/device.h)
---------------------------------- Structure:
struct device_attribute { struct attribute attr;
ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); };
Declaring:
DEVICE_ATTR(_name, _mode, _show, _store);
Creation/Removal:
int device_create_file(struct device *dev, const struct device_attribute * attr); void device_remove_file(struct device *dev, const struct device_attribute * attr);
- bus drivers (include/linux/device.h)
-------------------------------------- Structure:
struct bus_attribute { struct attribute        attr;
        ssize_t (*show)(struct bus_type *, char * buf);
        ssize_t (*store)(struct bus_type *, const char * buf, size_t count); };
Declaring:
BUS_ATTR(_name, _mode, _show, _store)
Creation/Removal:
int bus_create_file(struct bus_type *, struct bus_attribute *); void bus_remove_file(struct bus_type *, struct bus_attribute *);
- device drivers (include/linux/device.h)
-----------------------------------------
Structure:
struct driver_attribute { struct attribute        attr;
        ssize_t (*show)(struct device_driver *, char * buf);
        ssize_t (*store)(struct device_driver *, const char * buf, size_t count); };
Declaring:
DRIVER_ATTR(_name, _mode, _show, _store)
Creation/Removal:
int driver_create_file(struct device_driver *, const struct driver_attribute *); void driver_remove_file(struct device_driver *, const struct driver_attribute *);



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值