Move debugfs, rootfs and procfs documentation to README

This commit is contained in:
Ciro Santilli
2018-06-29 09:55:25 +01:00
parent 0cd1a2b602
commit 9a4eae50c8
11 changed files with 149 additions and 98 deletions

View File

@@ -2879,13 +2879,6 @@ You should then look up if there is a branch that supports that kernel. Staying
Pseudo filesystems are filesystems that don't represent actual files in a hard disk, but rather allow us to do special operations on filesystem-related system calls.
Some notable examples include:
* procfs, often mounted at: `/proc`
* sysfs, often mounted at: `/sys`
* devtmpfs, often mounted at: `/dev`
* debugfs, often mounted at: `/sys/kernel/debug/`
What each pseudo-file does for each related system call does is defined by its <<file-operations>>.
Bibliography:
@@ -2893,6 +2886,110 @@ Bibliography:
* https://superuser.com/questions/1198292/what-is-a-pseudo-file-system-in-linux
* https://en.wikipedia.org/wiki/Synthetic_file_system
==== debugfs
In guest:
....
/debugfs.sh
echo $?
....
Outcome: the test passes:
....
0
....
Sources:
* link:kernel_module/debugfs.c[]
* link:rootfs_overlay/debugfs.sh[]
Debugfs is the simplest pseudo filesystem to play around with, as it is made specifically to help test kernel stuff. Just mount, set <<file-operations>>, and we are done.
For this reason, it is the filesystem that we use whenever possible in our tests.
`debugfs.sh` explicitly mounts a debugfs at a custom location, but the most common mount point is `/sys/kernel/debug`.
This mount not done automatically by the kernel however: we, like most distros, do it from userland with our link:rootfs_overlay/etc/fstab[fstab].
Debugfs support requires the kernel to be compiled with `CONFIG_DEBUG_FS=y`.
Only the more basic file operations can be implemented in debugfs, e.g. `mmap` never gets called:
* https://patchwork.kernel.org/patch/9252557/
* https://github.com/torvalds/linux/blob/v4.9/fs/debugfs/file.c#L212
Bibliography: https://github.com/chadversary/debugfs-tutorial
==== procfs
In guest:
....
/procfs.sh
echo $?
....
Outcome: the test passes:
....
0
....
Sources:
* link:kernel_module/procfs.c[]
* link:rootfs_overlay/procfs.sh[]
Just another fops entry point.
Bibliography: https://stackoverflow.com/questions/8516021/proc-create-example-for-kernel-module/18924359#18924359
==== sysfs
In guest:
....
/sysfs.sh
echo $?
....
Outcome: the test passes:
....
0
....
Sources:
* link:kernel_module/sysfs.c[]
* link:rootfs_overlay/sysfs.sh[]
Vs procfs:
* https://unix.stackexchange.com/questions/4884/what-is-the-difference-between-procfs-and-sysfs
* https://stackoverflow.com/questions/37237835/how-to-attach-file-operations-to-sysfs-attribute-in-platform-driver
This example shows how sysfs is more restricted, as it does not take an arbitrary `file_operations`.
So you basically can only do `open`, `close`, `read`, `write`, and `lseek` on sysfs files.
It is similar to a `seq_file` file operation, except that write is also implemented.
TODO: what are those `kobject` structs? Make a more complex example that shows what they can do.
Bibliography:
* https://github.com/t3rm1n4l/kern-dev-tutorial/blob/1f036ef40fc4378f5c8d2842e55bcea7c6f8894a/05-sysfs/sysfs.c
* https://www.kernel.org/doc/Documentation/kobject.txt
* https://www.quora.com/What-are-kernel-objects-Kobj
* http://www.makelinux.net/ldd3/chp-14-sect-1
* https://www.win.tue.nl/~aeb/linux/lk/lk-13.html
=== Pseudo files
==== File operations
In guest:
@@ -2919,7 +3016,7 @@ File operations is the main method of userland driver communication.
No, there no official documentation: http://stackoverflow.com/questions/15213932/what-are-the-struct-file-operations-arguments
==== Character device
==== Character devices
In guest:
@@ -2940,7 +3037,7 @@ Sources:
* link:rootfs_overlay/mknoddev.sh[]
* link:kernel_module/character_device.c[]
Charcter device files are created with:
Character device files are created with:
....
mknod </dev/path_to_dev> c <major> <minor>
@@ -2967,7 +3064,7 @@ which means:
* `c` (first letter): this is a character device. Would be `b` for a block device.
* `1, 9`: the major number is `1`, and the minor `9`
To avoid device number conflicts when registring the driver we:
To avoid device number conflicts when registering the driver we:
* ask the kernel to allocate a free major number for us with: `register_chrdev(0`
* find ouf which number was assigned by grepping `/proc/devices` for the kernel module name

View File

@@ -20,14 +20,11 @@
... link:dep2.c[]
. Pseudo filesystems
.. link:anonymous_inode.c[]
.. link:debugfs.c[]
.. link:ioctl.c[]
.. link:mmap.c[]
.. link:poll.c[]
.. link:procfs.c[]
.. link:seq_file.c[]
.. link:seq_file_inode.c[]
.. link:sysfs.c[]
. Asynchronous
.. link:irq.c[]
.. link:kthread.c[]

View File

@@ -1,3 +1,5 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#character-devices */
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
#include <linux/module.h>
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */

View File

@@ -1,3 +1,5 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#automatically-create-character-device-file-on-insmod */
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */

View File

@@ -1,17 +1,4 @@
/*
Adapted from: https://github.com/chadversary/debugfs-tutorial/blob/47b3cf7ca47208c61ccb51b27aac6f9f932bfe0b/example1/debugfs_example1.c
Usage:
/debugfs.sh
Requires `CONFIG_DEBUG_FS=y`.
Only the more basic fops can be implemented in debugfs, e.g. mmap is never called:
- https://patchwork.kernel.org/patch/9252557/
- https://github.com/torvalds/linux/blob/v4.9/fs/debugfs/file.c#L212
*/
/* https://github.com/cirosantilli/linux-kernel-module-cheat#debugfs */
#include <linux/debugfs.h>
#include <linux/kernel.h>

View File

@@ -1,15 +1,4 @@
/*
Yet another fops entrypoint.
https://stackoverflow.com/questions/8516021/proc-create-example-for-kernel-module
insmod /procfs.ko
cat /proc/lkmc_procfs
Output:
abcd
*/
/* https://github.com/cirosantilli/linux-kernel-module-cheat#procfs */
#include <linux/debugfs.h>
#include <linux/module.h>

View File

@@ -1,24 +1,4 @@
/*
Adapted from: https://github.com/t3rm1n4l/kern-dev-tutorial/blob/1f036ef40fc4378f5c8d2842e55bcea7c6f8894a/05-sysfs/sysfs.c
Vs procfs:
- https://unix.stackexchange.com/questions/4884/what-is-the-difference-between-procfs-and-sysfs
- https://stackoverflow.com/questions/37237835/how-to-attach-file-operations-to-sysfs-attribute-in-platform-driver
This example shows how sysfs is more restricted, as it does not take a file_operations.
So you basically can only do open, close, read, write, and lseek on sysfs files.
It is kind of similar to a seq_file file_operations, except that write is also implemented.
TODO: what are those kobject structs? Make a more complex example that shows what they can do.
- https://www.kernel.org/doc/Documentation/kobject.txt
- https://www.quora.com/What-are-kernel-objects-Kobj
- http://www.makelinux.net/ldd3/chp-14-sect-1
- https://www.win.tue.nl/~aeb/linux/lk/lk-13.html
*/
/* https://github.com/cirosantilli/linux-kernel-module-cheat#sysfs */
#include <linux/init.h>
#include <linux/kobject.h>

View File

@@ -1,22 +1,13 @@
#!/bin/sh
set -ex
set -e
d=/debugfs
mkdir -p "$d"
# We also added a fstab entry that mounts this under /sys/kernel/debug autmoatically.
# That is the most common place to mount it.
# The /sys/kernel/debug directory gets created automatically when debugfs is
# compiled into the kernel, but it does not get mounted automatically.
mount -t debugfs none /debugfs
mount -t debugfs none "$d"
insmod /debugfs.ko
cd "${d}/lkmc_debugfs"
cat myfile
# => 42
echo 13 > myfile
cat myfile
# => 13
[ "$(cat "${d}/lkmc_debugfs/myfile")" = 42 ]
echo 13 > "${d}/lkmc_debugfs/myfile"
[ "$(cat "${d}/lkmc_debugfs/myfile")" = 13 ]
echo 666 > "${d}/lkmc_debugfs_file"
cat myfile
# => 666
[ "$(cat "${d}/lkmc_debugfs/myfile")" = 666 ]
rmmod debugfs
umount "$d"

5
rootfs_overlay/procfs.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
set -e
insmod /procfs.ko
[ "$(cat "/proc/lkmc_procfs")" = abcd ]
rmmod procfs

View File

@@ -1,11 +1,11 @@
#!/bin/sh
set -x
set -e
insmod /sysfs.ko
cd /sys/kernel/lkmc_sysfs
printf 12345 >foo
cat foo
# => 1234
dd if=foo bs=1 count=2 skip=1 status=none
# => 23
f=/sys/kernel/lkmc_sysfs/foo
# write
printf 12345 > "$f"
# read
[ "$(cat "$f")" = 1234 ]
# seek
[ "$(dd if="$f" bs=1 count=2 skip=1 status=none)" = 23 ]
rmmod sysfs

View File

@@ -1,14 +1,15 @@
#!/bin/sh
(
set -ex
/character_device.sh
/character_device_create.sh
/fops.sh
)
if [ "$?" -eq 0 ]; then
echo lkmc_test_pass
exit 0
else
echo lkmc_test_fail
exit 1
fi
for test in \
/character_device.sh \
/character_device_create.sh \
/debugfs.sh \
/fops.sh \
/procfs.sh \
/sysfs.sh
do
if ! "$test"; then
echo "lkmc_test_fail: ${test}"
exit 1
fi
done
echo lkmc_test_pass