sysfs - _The_ filesystem for exporting kernel objects.
Patrick Mochel <mochel@osdl.org>
+Mike Murphy <mamurph@cs.clemson.edu>
-10 January 2003
+Revised: 22 February 2009
+Original: 10 January 2003
What it is:
Using sysfs
~~~~~~~~~~~
-sysfs is always compiled in. You can access it by doing:
+sysfs is always compiled in if CONFIG_SYSFS is defined. You can access
+it by doing:
mount -t sysfs sysfs /sys
attributes.
Attributes should be ASCII text files, preferably with only one value
-per file. It is noted that it may not be efficient to contain only
+per file. It is noted that it may not be efficient to contain only one
value per file, so it is socially acceptable to express an array of
values of the same type.
struct attribute {
char * name;
+ struct module *owner;
mode_t mode;
};
-int sysfs_create_file(struct kobject * kobj, struct attribute * attr);
-void sysfs_remove_file(struct kobject * kobj, struct attribute * attr);
+int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
+void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
A bare attribute contains no means to read or write the value of the
For example, the driver model defines struct device_attribute like:
struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf);
- ssize_t (*store)(struct device * dev, const char * buf);
+ 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 *, 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 = __stringify(_name) , .mode = _mode }, \
- .show = _show, \
- .store = _store, \
-};
+#define DEVICE_ATTR(_name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
For example, declaring
.attr = {
.name = "foo",
.mode = S_IWUSR | S_IRUGO,
+ .show = show_foo,
+ .store = store_foo,
},
- .show = show_foo,
- .store = store_foo,
};
specified when declaring the attribute. The method types should be as
simple as those defined for device attributes:
- ssize_t (*show)(struct device * dev, char * buf);
- ssize_t (*store)(struct device * dev, const char * buf);
+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);
-IOW, they should take only an object and a buffer as parameters.
+IOW, they should take only an object, an attribute, and a buffer as parameters.
sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
Recall that an attribute should only be exporting one value, or an
array of similar values, so this shouldn't be that expensive.
- This allows userspace to do partial reads and seeks arbitrarily over
- the entire file at will.
+ This allows userspace to do partial reads and forward seeks
+ arbitrarily over the entire file at will. If userspace seeks back to
+ zero or does a pread(2) with an offset of '0' the show() method will
+ be called again, rearmed, to fill the buffer.
- On write(2), sysfs expects the entire buffer to be passed during the
first write. Sysfs then passes the entire buffer to the store()
Other notes:
+- Writing causes the show() method to be rearmed regardless of current
+ file position.
+
- The buffer will always be PAGE_SIZE bytes in length. On i386, this
is 4096.
The sysfs directory arrangement exposes the relationship of kernel
data structures.
-The top level sysfs diretory looks like:
+The top level sysfs directory looks like:
block/
bus/
class/
+dev/
devices/
firmware/
net/
+fs/
devices/ contains a filesystem representation of the device tree. It maps
directly to the internal kernel device tree, which is a hierarchy of
for devices on that particular bus (this assumes that drivers do not
span multiple bus types).
+fs/ contains a directory for some filesystems. Currently each
+filesystem wanting to export attributes must create its own hierarchy
+below fs/ (see ./fuse.txt for an example).
+
+dev/ contains two directories char/ and block/. Inside these two
+directories there are symlinks named <major>:<minor>. These symlinks
+point to the sysfs directory for the given device. /sys/dev provides a
+quick way to lookup the sysfs interface for a device from the result of
+a stat(2) operation.
More information can driver-model specific features can be found in
Documentation/driver-model/.
Structure:
struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf);
- ssize_t (*store)(struct device * dev, const char * buf);
+ 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, _str, _mode, _show, _store);
+DEVICE_ATTR(_name, _mode, _show, _store);
Creation/Removal:
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *, char * buf);
- ssize_t (*store)(struct device_driver *, const char * buf);
+ ssize_t (*store)(struct device_driver *, const char * buf,
+ size_t count);
};
Declaring: