Skip to content

Commit 084e3fa

Browse files
committed
seq_file: move doc to README
1 parent 923f655 commit 084e3fa

File tree

9 files changed

+97
-82
lines changed

9 files changed

+97
-82
lines changed

README.adoc

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2976,7 +2976,7 @@ This example shows how sysfs is more restricted, as it does not take an arbitrar
29762976

29772977
So you basically can only do `open`, `close`, `read`, `write`, and `lseek` on sysfs files.
29782978

2979-
It is similar to a `seq_file` file operation, except that write is also implemented.
2979+
It is similar to a <<seq_file>> file operation, except that write is also implemented.
29802980

29812981
TODO: what are those `kobject` structs? Make a more complex example that shows what they can do.
29822982

@@ -3024,6 +3024,76 @@ File operations is the main method of userland driver communication.
30243024

30253025
No, there no official documentation: http://stackoverflow.com/questions/15213932/what-are-the-struct-file-operations-arguments
30263026

3027+
==== seq_file
3028+
3029+
In guest:
3030+
3031+
....
3032+
/seq_file.sh
3033+
echo $?
3034+
....
3035+
3036+
Outcome: the test passes:
3037+
3038+
....
3039+
0
3040+
....
3041+
3042+
Sources:
3043+
3044+
* link:kernel_module/seq_file.c[]
3045+
* link:rootfs_overlay/seq_file.sh[]
3046+
3047+
Writing trivial read <<file-operations>> is repetitive and error prone.
3048+
3049+
The `seq_file` API makes the process much easier for those trivial cases.
3050+
3051+
In this example we create a debugfs file that behaves just like a file that contains:
3052+
3053+
....
3054+
0
3055+
1
3056+
2
3057+
....
3058+
3059+
However, we only store a single integer in memory and calculate the file on the fly in an iterator fashion.
3060+
3061+
`seq_file` does not provide `write`: https://stackoverflow.com/questions/30710517/how-to-implement-a-writable-proc-file-by-using-seq-file-in-a-driver-module
3062+
3063+
Bibliography:
3064+
3065+
* link:https://github.com/torvalds/linux/blob/v4.17/Documentation/filesystems/seq_file.txt[Documentation/filesystems/seq_file.txt]
3066+
* https://stackoverflow.com/questions/25399112/how-to-use-a-seq-file-in-linux-modules
3067+
3068+
===== seq_file single_open
3069+
3070+
In guest:
3071+
3072+
....
3073+
/seq_file.sh
3074+
echo $?
3075+
....
3076+
3077+
Outcome: the test passes:
3078+
3079+
....
3080+
0
3081+
....
3082+
3083+
Sources:
3084+
3085+
* link:kernel_module/seq_file_single_open.c[]
3086+
* link:rootfs_overlay/seq_file_single_open.sh[]
3087+
3088+
If you have the entire read output upfront, `single_open` is an even more convenient version of <<seq_file>>.
3089+
3090+
This example produces a debugfs file that behaves like a file that contains:
3091+
3092+
....
3093+
ab
3094+
cd
3095+
....
3096+
30273097
==== Character devices
30283098

30293099
In guest:
@@ -3123,10 +3193,9 @@ Sources:
31233193
* link:kernel_module/user/anonymous_inode.c[]
31243194
* link:rootfs_overlay/anonymous_inode.sh[]
31253195

3126-
This example:
3196+
This example gets an anonymous inode via `ioctl` from a debugfs entry by using `anon_inode_getfd`.
31273197

3128-
* gets an anonymous inode via `ioctl` from a debugfs entry `anon_inode_getfd` from a debugfs file
3129-
* read jiffies from that inode
3198+
Reads to that inode return the sequence: `1`, `10`, `100`, ... `10000000`, `1`, `100`, ...
31303199

31313200
Anonymous inodes allow getting multiple file descriptors from a single filesystem entry, which reduces namespace pollution compared to creating multiple device files.
31323201

kernel_module/README.adoc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
.. link:ioctl.c[]
2323
.. link:mmap.c[]
2424
.. link:poll.c[]
25-
.. link:seq_file.c[]
26-
.. link:seq_file_inode.c[]
2725
. Asynchronous
2826
.. link:irq.c[]
2927
.. link:kthread.c[]

kernel_module/anonymous_inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off
2424
ret = -EFAULT;
2525
}
2626
myval <<= 4;
27+
if (myval == 0) {
28+
myval = 1;
29+
}
2730
return ret;
2831
}
2932

kernel_module/seq_file.c

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,4 @@
1-
/*
2-
Adapted from: Documentation/filesystems/seq_file.txt
3-
but we limit the count to the max module parameter.
4-
5-
Writting trivial read fops is repetitive and error prone.
6-
7-
The seq_file API makes the process much easier for those trivial cases.
8-
9-
This example is behaves just like a file that contains:
10-
11-
0
12-
1
13-
2
14-
15-
However, we only store a single integer in memory
16-
and calculate the file on the fly in an iterator fashion.
17-
18-
There is not write version, as writes are more complex:
19-
https://stackoverflow.com/questions/30710517/how-to-implement-a-writable-proc-file-by-using-seq-file-in-a-driver-module
20-
21-
Bibliography:
22-
23-
- Documentation/filesystems/seq_file.txt
24-
- https://stackoverflow.com/questions/25399112/how-to-use-a-seq-file-in-linux-modules
25-
*/
1+
/* https://github.com/cirosantilli/linux-kernel-module-cheat#seq_file */
262

273
#include <linux/debugfs.h>
284
#include <linux/errno.h> /* EFAULT */

kernel_module/seq_file_single.c renamed to kernel_module/seq_file_single_open.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
1-
/*
2-
If you have the entire read output upfront, single_open
3-
is an even more convenient version of seq_file.
4-
5-
This example behaves like a file that contains:
6-
7-
ab
8-
cd
9-
*/
1+
/* https://github.com/cirosantilli/linux-kernel-module-cheat#seq_file-single_open */
102

113
#include <linux/debugfs.h>
124
#include <linux/errno.h> /* EFAULT */
@@ -40,8 +32,7 @@ static const struct file_operations fops = {
4032

4133
static int myinit(void)
4234
{
43-
debugfs_file = debugfs_create_file(
44-
"lkmc_seq_file_single", S_IRUSR, NULL, NULL, &fops);
35+
debugfs_file = debugfs_create_file("lkmc_seq_file_single_open", S_IRUSR, NULL, NULL, &fops);
4536
return 0;
4637
}
4738

rootfs_overlay/seq_file.sh

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,10 @@
11
#!/bin/sh
2-
3-
set -ex
4-
2+
set -e
3+
f=/sys/kernel/debug/lkmc_seq_file
54
insmod /seq_file.ko
6-
cd /sys/kernel/debug
7-
8-
cat 'lkmc_seq_file'
9-
# => 0
10-
# => 1
11-
# => 2
12-
13-
cat 'lkmc_seq_file'
14-
# => 0
15-
# => 1
16-
# => 2
17-
18-
dd if='lkmc_seq_file' bs=1 count=2 skip=0 status=none
19-
# => 0
20-
dd if='lkmc_seq_file' bs=1 count=4 skip=0 status=none
21-
# => 0
22-
# => 1
23-
dd if='lkmc_seq_file' bs=1 count=2 skip=2 status=none
24-
# => 1
25-
dd if='lkmc_seq_file' bs=4 count=1 skip=0 status=none
26-
# => 0
27-
# => 1
28-
5+
[ "$(cat "$f")" = "$(printf '0\n1\n2\n')" ]
6+
[ "$(cat "$f")" = "$(printf '0\n1\n2\n')" ]
7+
[ "$(dd if="$f" bs=1 count=2 skip=0 status=none)" = "$(printf '0\n')" ]
8+
[ "$(dd if="$f" bs=1 count=2 skip=2 status=none)" = "$(printf '1\n')" ]
9+
[ "$(dd if="$f" bs=4 count=1 skip=0 status=none)" = "$(printf '0\n1\n')" ]
2910
rmmod seq_file

rootfs_overlay/seq_file_single.sh

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
set -e
3+
f=/sys/kernel/debug/lkmc_seq_file_single_open
4+
insmod /seq_file_single_open.ko
5+
[ "$(cat "$f")" = "$(printf 'ab\ncd\n')" ]
6+
[ "$(dd if="$f" bs=1 count=3 skip=1)" = "$(printf "b\nc\n")" ]
7+
rmmod seq_file_single_open

rootfs_overlay/test_all.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ for test in \
66
/debugfs.sh \
77
/fops.sh \
88
/procfs.sh \
9-
/sysfs.sh
10-
do
9+
/seq_file.sh \
10+
/seq_file_single_open.sh \
11+
/sysfs.sh \
12+
; do
1113
if ! "$test"; then
1214
echo "lkmc_test_fail: ${test}"
1315
exit 1

0 commit comments

Comments
 (0)