From 9a4eae50c841aaf59e140124e166eca8f3649db8 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Fri, 29 Jun 2018 09:55:25 +0100 Subject: [PATCH] Move debugfs, rootfs and procfs documentation to README --- README.adoc | 117 ++++++++++++++++++++++-- kernel_module/README.adoc | 3 - kernel_module/character_device.c | 2 + kernel_module/character_device_create.c | 2 + kernel_module/debugfs.c | 15 +-- kernel_module/procfs.c | 13 +-- kernel_module/sysfs.c | 22 +---- rootfs_overlay/debugfs.sh | 25 ++--- rootfs_overlay/procfs.sh | 5 + rootfs_overlay/sysfs.sh | 16 ++-- rootfs_overlay/test_all.sh | 27 +++--- 11 files changed, 149 insertions(+), 98 deletions(-) create mode 100755 rootfs_overlay/procfs.sh diff --git a/README.adoc b/README.adoc index 06cbe02..c6597ce 100644 --- a/README.adoc +++ b/README.adoc @@ -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 <>. 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 <>, 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 c @@ -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 diff --git a/kernel_module/README.adoc b/kernel_module/README.adoc index f6ca0b7..780e215 100644 --- a/kernel_module/README.adoc +++ b/kernel_module/README.adoc @@ -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[] diff --git a/kernel_module/character_device.c b/kernel_module/character_device.c index 8a2049d..eb9cba8 100644 --- a/kernel_module/character_device.c +++ b/kernel_module/character_device.c @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#character-devices */ + #include /* register_chrdev, unregister_chrdev */ #include #include /* seq_read, seq_lseek, single_release */ diff --git a/kernel_module/character_device_create.c b/kernel_module/character_device_create.c index bbd2b43..de51964 100644 --- a/kernel_module/character_device_create.c +++ b/kernel_module/character_device_create.c @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#automatically-create-character-device-file-on-insmod */ + #include #include #include /* register_chrdev, unregister_chrdev */ diff --git a/kernel_module/debugfs.c b/kernel_module/debugfs.c index 91c967a..c6016e0 100644 --- a/kernel_module/debugfs.c +++ b/kernel_module/debugfs.c @@ -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 #include diff --git a/kernel_module/procfs.c b/kernel_module/procfs.c index 010647e..ae7529a 100644 --- a/kernel_module/procfs.c +++ b/kernel_module/procfs.c @@ -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 #include diff --git a/kernel_module/sysfs.c b/kernel_module/sysfs.c index 79bd56e..7319447 100644 --- a/kernel_module/sysfs.c +++ b/kernel_module/sysfs.c @@ -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 #include diff --git a/rootfs_overlay/debugfs.sh b/rootfs_overlay/debugfs.sh index 08a4135..07eac5a 100755 --- a/rootfs_overlay/debugfs.sh +++ b/rootfs_overlay/debugfs.sh @@ -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" diff --git a/rootfs_overlay/procfs.sh b/rootfs_overlay/procfs.sh new file mode 100755 index 0000000..208bd8b --- /dev/null +++ b/rootfs_overlay/procfs.sh @@ -0,0 +1,5 @@ +#!/bin/sh +set -e +insmod /procfs.ko +[ "$(cat "/proc/lkmc_procfs")" = abcd ] +rmmod procfs diff --git a/rootfs_overlay/sysfs.sh b/rootfs_overlay/sysfs.sh index 73a1d63..397af98 100755 --- a/rootfs_overlay/sysfs.sh +++ b/rootfs_overlay/sysfs.sh @@ -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 diff --git a/rootfs_overlay/test_all.sh b/rootfs_overlay/test_all.sh index ee6cc88..22e2a17 100755 --- a/rootfs_overlay/test_all.sh +++ b/rootfs_overlay/test_all.sh @@ -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