Debugfs is the most flexible of the standard Linux kernel interfacing techniques, and it exists purely to make debugging easier, without imposing the strict formatting rules that sysfs enforces. If you’ve been following this free Linux kernel programming course from the start, debugfs will feel refreshingly simple after sysfs’s one-value-per-file discipline.
Where sysfs demands one clean value per file, debugfs places no such restriction on you: a single file can print a multi-line dump of internal state, a formatted table, or anything else useful for diagnosis. This freedom is exactly why the kernel community reserves debugfs strictly for development and debugging purposes rather than as a stable, user-facing driver API.
| sysfs Strict, one value per file, part of device model |
vs | debugfs Free-form, any format, debugging only |
On most modern distributions debugfs is already mounted at /sys/kernel/debug. If it isn’t, you can mount it manually as root:
mount -t debugfs none /sys/kernel/debug
The debugfs API offers ready-made helpers for common data types so you rarely need to write your own file operations. Here is an original example exposing a 32-bit counter:
#include <linux/debugfs.h>
static u32 packet_counter;
static struct dentry *mydrv_debug_dir;
static int __init mydrv_init(void)
{
mydrv_debug_dir = debugfs_create_dir("mydriver", NULL);
debugfs_create_u32("packet_counter", 0444,
mydrv_debug_dir, &packet_counter);
return 0;
}
static void __exit mydrv_exit(void)
{
debugfs_remove_recursive(mydrv_debug_dir);
}
Reading the value from user space is then as simple as:
cat /sys/kernel/debug/mydriver/packet_counter
| Mistake | Fix |
|---|---|
| Treating debugfs as a stable API for applications | Restrict it to debugging; use sysfs for production ABI |
| Forgetting debugfs_remove_recursive() on unload | Always clean up the debugfs directory in your exit function |
| Assuming debugfs is always mounted | Check /sys/kernel/debug or mount it explicitly |
- Group all entries for one driver under a single debugfs directory.
- Use the built-in
debugfs_create_u32/u64/bool/blobhelpers instead of custom file operations when possible. - Guard debugfs code with
CONFIG_DEBUG_FSchecks if it must compile cleanly when debugfs is disabled.
Debugfs entries are typically restricted to root by default configuration, but you should still avoid exposing sensitive internal data or writable entries that could destabilize the system if misused, since debugfs bypasses much of the structure that keeps sysfs predictable.
- Debugfs trades structure for flexibility, ideal for development-time diagnostics.
- It should never be relied upon as a stable, production-facing interface.
- Built-in helper functions cover most common debugging data types.
- Always clean up debugfs entries when your module unloads.
Q1. Is debugfs available in production kernels?
It usually is, but relying on it for production functionality is discouraged since it is meant strictly for development and debugging.
Q2. Where is debugfs mounted?
Typically at /sys/kernel/debug, though it needs to be mounted explicitly on some minimal systems.
Q3. Can debugfs entries have any format?
Yes, unlike sysfs, debugfs does not enforce a one-value-per-file convention, so entries can contain multi-line or arbitrarily formatted output.
Q4. Do I need to remove debugfs entries manually?
Yes, you should call debugfs_remove_recursive() in your module’s exit function to avoid leaving stale entries behind.
Q5. Is debugfs a good place for driver configuration options?
No, configuration meant for regular use belongs in sysfs; debugfs is for temporary, developer-facing diagnostics only.

2 Comments