mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-26 19:51:35 +01:00
Move debugfs, rootfs and procfs documentation to README
This commit is contained in:
117
README.adoc
117
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.
|
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>>.
|
What each pseudo-file does for each related system call does is defined by its <<file-operations>>.
|
||||||
|
|
||||||
Bibliography:
|
Bibliography:
|
||||||
@@ -2893,6 +2886,110 @@ Bibliography:
|
|||||||
* https://superuser.com/questions/1198292/what-is-a-pseudo-file-system-in-linux
|
* https://superuser.com/questions/1198292/what-is-a-pseudo-file-system-in-linux
|
||||||
* https://en.wikipedia.org/wiki/Synthetic_file_system
|
* 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
|
==== File operations
|
||||||
|
|
||||||
In guest:
|
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
|
No, there no official documentation: http://stackoverflow.com/questions/15213932/what-are-the-struct-file-operations-arguments
|
||||||
|
|
||||||
==== Character device
|
==== Character devices
|
||||||
|
|
||||||
In guest:
|
In guest:
|
||||||
|
|
||||||
@@ -2940,7 +3037,7 @@ Sources:
|
|||||||
* link:rootfs_overlay/mknoddev.sh[]
|
* link:rootfs_overlay/mknoddev.sh[]
|
||||||
* link:kernel_module/character_device.c[]
|
* 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>
|
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.
|
* `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`
|
* `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`
|
* 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
|
* find ouf which number was assigned by grepping `/proc/devices` for the kernel module name
|
||||||
|
|||||||
@@ -20,14 +20,11 @@
|
|||||||
... link:dep2.c[]
|
... link:dep2.c[]
|
||||||
. Pseudo filesystems
|
. Pseudo filesystems
|
||||||
.. link:anonymous_inode.c[]
|
.. link:anonymous_inode.c[]
|
||||||
.. link:debugfs.c[]
|
|
||||||
.. link:ioctl.c[]
|
.. link:ioctl.c[]
|
||||||
.. link:mmap.c[]
|
.. link:mmap.c[]
|
||||||
.. link:poll.c[]
|
.. link:poll.c[]
|
||||||
.. link:procfs.c[]
|
|
||||||
.. link:seq_file.c[]
|
.. link:seq_file.c[]
|
||||||
.. link:seq_file_inode.c[]
|
.. link:seq_file_inode.c[]
|
||||||
.. link:sysfs.c[]
|
|
||||||
. Asynchronous
|
. Asynchronous
|
||||||
.. link:irq.c[]
|
.. link:irq.c[]
|
||||||
.. link:kthread.c[]
|
.. link:kthread.c[]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#character-devices */
|
||||||
|
|
||||||
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
|
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */
|
#include <linux/seq_file.h> /* seq_read, seq_lseek, single_release */
|
||||||
|
|||||||
@@ -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/cdev.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
|
#include <linux/fs.h> /* register_chrdev, unregister_chrdev */
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
/*
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#debugfs */
|
||||||
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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|||||||
@@ -1,15 +1,4 @@
|
|||||||
/*
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#procfs */
|
||||||
Yet another fops entrypoint.
|
|
||||||
|
|
||||||
https://stackoverflow.com/questions/8516021/proc-create-example-for-kernel-module
|
|
||||||
|
|
||||||
insmod /procfs.ko
|
|
||||||
cat /proc/lkmc_procfs
|
|
||||||
|
|
||||||
Output:
|
|
||||||
|
|
||||||
abcd
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|||||||
@@ -1,24 +1,4 @@
|
|||||||
/*
|
/* https://github.com/cirosantilli/linux-kernel-module-cheat#sysfs */
|
||||||
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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
|
|||||||
@@ -1,22 +1,13 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -ex
|
set -e
|
||||||
d=/debugfs
|
d=/debugfs
|
||||||
mkdir -p "$d"
|
mkdir -p "$d"
|
||||||
# We also added a fstab entry that mounts this under /sys/kernel/debug autmoatically.
|
mount -t debugfs none "$d"
|
||||||
# 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
|
|
||||||
insmod /debugfs.ko
|
insmod /debugfs.ko
|
||||||
cd "${d}/lkmc_debugfs"
|
[ "$(cat "${d}/lkmc_debugfs/myfile")" = 42 ]
|
||||||
|
echo 13 > "${d}/lkmc_debugfs/myfile"
|
||||||
cat myfile
|
[ "$(cat "${d}/lkmc_debugfs/myfile")" = 13 ]
|
||||||
# => 42
|
|
||||||
|
|
||||||
echo 13 > myfile
|
|
||||||
cat myfile
|
|
||||||
# => 13
|
|
||||||
|
|
||||||
echo 666 > "${d}/lkmc_debugfs_file"
|
echo 666 > "${d}/lkmc_debugfs_file"
|
||||||
cat myfile
|
[ "$(cat "${d}/lkmc_debugfs/myfile")" = 666 ]
|
||||||
# => 666
|
rmmod debugfs
|
||||||
|
umount "$d"
|
||||||
|
|||||||
5
rootfs_overlay/procfs.sh
Executable file
5
rootfs_overlay/procfs.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
insmod /procfs.ko
|
||||||
|
[ "$(cat "/proc/lkmc_procfs")" = abcd ]
|
||||||
|
rmmod procfs
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
set -x
|
|
||||||
insmod /sysfs.ko
|
insmod /sysfs.ko
|
||||||
cd /sys/kernel/lkmc_sysfs
|
f=/sys/kernel/lkmc_sysfs/foo
|
||||||
printf 12345 >foo
|
# write
|
||||||
cat foo
|
printf 12345 > "$f"
|
||||||
# => 1234
|
# read
|
||||||
dd if=foo bs=1 count=2 skip=1 status=none
|
[ "$(cat "$f")" = 1234 ]
|
||||||
# => 23
|
# seek
|
||||||
|
[ "$(dd if="$f" bs=1 count=2 skip=1 status=none)" = 23 ]
|
||||||
rmmod sysfs
|
rmmod sysfs
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
(
|
for test in \
|
||||||
set -ex
|
/character_device.sh \
|
||||||
/character_device.sh
|
/character_device_create.sh \
|
||||||
/character_device_create.sh
|
/debugfs.sh \
|
||||||
/fops.sh
|
/fops.sh \
|
||||||
)
|
/procfs.sh \
|
||||||
if [ "$?" -eq 0 ]; then
|
/sysfs.sh
|
||||||
echo lkmc_test_pass
|
do
|
||||||
exit 0
|
if ! "$test"; then
|
||||||
else
|
echo "lkmc_test_fail: ${test}"
|
||||||
echo lkmc_test_fail
|
exit 1
|
||||||
exit 1
|
fi
|
||||||
fi
|
done
|
||||||
|
echo lkmc_test_pass
|
||||||
|
|||||||
Reference in New Issue
Block a user