Skip to content

Commit 96e522c

Browse files
authored
Merge pull request sysprog21#150 from asas1asas200/zeng-feat-attributes
Add description of sysfs attribute
2 parents 565a599 + 04465b1 commit 96e522c

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

examples/vinput.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* vinput.c
3+
*/
4+
15
#include <linux/cdev.h>
26
#include <linux/input.h>
37
#include <linux/module.h>

examples/vinput.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* vinput.h
3+
*/
4+
15
#ifndef VINPUT_H
26
#define VINPUT_H
37

examples/vkbd.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* vkbd.c
3+
*/
4+
15
#include <linux/init.h>
26
#include <linux/input.h>
37
#include <linux/module.h>

lkmpg.tex

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,40 @@ \section{sysfs: Interacting with your module}
12571257
ls -l /sys
12581258
\end{codebash}
12591259

1260+
Attributes can be exported for kobjects in the form of regular files in the filesystem.
1261+
Sysfs forwards file I/O operations to methods defined for the attributes, providing a means to read and write kernel attributes.
1262+
1263+
An attribute definition in simply:
1264+
1265+
\begin{code}
1266+
struct attribute {
1267+
char *name;
1268+
struct module *owner;
1269+
umode_t mode;
1270+
};
1271+
1272+
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
1273+
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
1274+
\end{code}
1275+
1276+
For example, the driver model defines \cpp|struct device_attribute| like:
1277+
1278+
\begin{code}
1279+
struct device_attribute {
1280+
struct attribute attr;
1281+
ssize_t (*show)(struct device *dev, struct device_attribute *attr,
1282+
char *buf);
1283+
ssize_t (*store)(struct device *dev, struct device_attribute *attr,
1284+
const char *buf, size_t count);
1285+
};
1286+
1287+
int device_create_file(struct device *, const struct device_attribute *);
1288+
void device_remove_file(struct device *, const struct device_attribute *);
1289+
\end{code}
1290+
1291+
To read or write attributes, \cpp|show()| or \cpp|store()| method must be specified when declaring the attribute.
1292+
For the common cases \src{include/linux/sysfs.h} provides convenience macros (\cpp|__ATTR|, \cpp|__ATTR_RO|, \cpp|__ATTR_WO|, etc.) to make defining attributes easier as well as making code more concise and readable.
1293+
12601294
An example of a hello world module which includes the creation of a variable accessible via sysfs is given below.
12611295

12621296
\samplec{examples/hello-sysfs.c}
@@ -1293,6 +1327,12 @@ \section{sysfs: Interacting with your module}
12931327
sudo rmmod hello_sysfs
12941328
\end{codebash}
12951329

1330+
In the above case, we use a simple kobject to create a directory under sysfs, and communicate with its attributes.
1331+
Since Linux v2.6.0, the \cpp|kobject| structure made its appearance.
1332+
It was initially meant as a simple way of unifying kernel code which manages reference counted objects.
1333+
After a bit of mission creep, it is now the glue that holds much of the device model and its sysfs interface together.
1334+
For more information about kobject and sysfs, see \src{Documentation/driver-api/driver-model/driver.rst} and \url{https://lwn.net/Articles/51437/}.
1335+
12961336
\section{Talking To Device Files}
12971337
\label{sec:device_files}
12981338
Device files are supposed to represent physical devices.
@@ -1897,6 +1937,23 @@ \section{Virtual Input Device Driver}
18971937
vinput devices are created and destroyed using sysfs.
18981938
And, event injection is done through a \verb|/dev| node.
18991939
The device name will be used by the userland to export a new virtual input device.
1940+
1941+
The \cpp|class_attribute| structure is similar to other attribute types we talked about in section \ref{sec:sysfs}:
1942+
1943+
\begin{code}
1944+
struct class_attribute {
1945+
struct attribute attr;
1946+
ssize_t (*show)(struct class *class, struct class_attribute *attr,
1947+
char *buf);
1948+
ssize_t (*store)(struct class *class, struct class_attribute *attr,
1949+
const char *buf, size_t count);
1950+
};
1951+
\end{code}
1952+
1953+
In \verb|vinput.c|, the macro \cpp|CLASS_ATTR_WO(export/unexport)| defined in \src{include/linux/device.h} (in this case, \verb|device.h| is included in \src{include/linux/input.h}) will generate the \cpp|class_attribute| structures which are named \verb|class_attr_export/unexport|.
1954+
Then, put them into \cpp|vinput_class_attrs| array and the macro \cpp|ATTRIBUTE_GROUPS(vinput_class)| will generate the \cpp|struct attribute_group vinput_class_group| that should be assigned in \cpp|vinput_class|.
1955+
Finally, call \cpp|class_register(&vinput_class)| to create attributes in sysfs.
1956+
19001957
To create a \verb|vinputX| sysfs entry and \verb|/dev| node.
19011958

19021959
\begin{codebash}
@@ -1933,7 +1990,6 @@ \section{Virtual Input Device Driver}
19331990

19341991
\samplec{examples/vkbd.c}
19351992

1936-
% TODO: Add description of attribute
19371993
% TODO: Add vts.c and vmouse.c example
19381994

19391995
\section{Standardizing the interfaces: The Device Model}

0 commit comments

Comments
 (0)