debugfs ======= .. tab-set:: .. tab-item:: debugfs * In this program, you are going to learn .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to debug the kernel code ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use below APIs ? * `debugfs_create_dir `_ * `debugfs_create_file `_ * `debugfs_create_u64 `_ * `debugfs_remove_recursive `_ .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Topics in this section, * :ref:`Explanation of program part by part ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initialize variables and functions ` * :ref:`Module init function ` * :ref:`Module exit function ` * :ref:`debugfs APIs ` * :ref:`mention init and exit function ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Summary of debugfs APIs ` .. _p3_debugfs_4: .. tab-set:: .. tab-item:: Explanation of program part by part * Here is the explanation of the source code. .. _p3_debugfs_5: .. tab-set:: .. tab-item:: List of headers * Add the list of headers to refer the APIs used in the source code. .. code-block:: c #include #include #include #include #include #include #include #include #include #include #include #include .. _p3_debugfs_6: .. tab-set:: .. tab-item:: Modules macros * Add the module macros which contains the information about macros such as author, description and license. .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux_usr"); MODULE_DESCRIPTION("Simple Linux Device Driver - debugfs"); .. _p3_debugfs_7: .. tab-set:: .. tab-item:: Initialize function and variables * Initialize the functions and the variables which are used in the source code. .. code-block:: c u64 intvalue, hexvalue; struct dentry *dirret, *fileret, *u64int, *u64hex; char ker_buf[len]; int filevalue; .. _p3_debugfs_8: .. tab-set:: .. tab-item:: Module init functions * Add the module init function to execute once when the module is loaded. .. code-block:: c static int __init init_debug(void) { /* create a directory by the name dell in /sys/kernel/debugfs */ dirret = debugfs_create_dir("dell", NULL); /* create a file in the above directory. This requires read and write file operations */ fileret = debugfs_create_file("text", 0004, dirret, &filevalue, &fops_debug); /* create a file which takes in a int(64) value */ u64int = debugfs_create_u64("number", 0004, dirret, &intvalue); if (!u64int) { pr_err("error creating int file"); return -ENODEV; } /* takes a hex decimal value */ u64hex = debugfs_create_x64("hexnum", 0004, dirret, &hexvalue); if (!u64hex) { pr_err("error creating hex file"); return -ENODEV; } pr_info("Device Driver Loaded..\n"); return 0; } * To be able to use ``debugfs``, we start by creating a directory within ``/sys/kernel/debug``, which is an ideal way to start. The rest of the files can be placed within this directory. .. code-block:: c dirret = debugfs_create_dir("dell", NULL); * If you need to create a single file within debugfs, you can the ``debugfs_create_file``. * To create a file in the above directory. This requires read and write file operation .. code-block:: c fileret = debugfs_create_file("text", 0004, dirret, &filevalue, &fops_debug); * To create a file which takes in a int(64) value .. code-block:: c u64int = debugfs_create_u64("number", 0004, dirret, &intvalue) * It takes a hex decimal value .. code-block:: c u64hex = debugfs_create_x64("hexnum", 0004, dirret, &hexvalue .. _p3_debugfs_9: .. tab-set:: .. tab-item:: Module exit function * Add the module exit function which is executed when the module is unloaded from the kernel. .. code-block:: c static void __exit exit_debug(void) { debugfs_remove_recursive(dirret); pr_info("Device Driver Unloaded..\n"); } * ``debugfs_remove_recursive`` used to cleanup all the files and directories created. .. code-block:: c debugfs_remove_recursive(dirret); .. _p3_debugfs_11: .. tab-set:: .. tab-item:: Add debugfs APIs * Add debugfs APIs .. code-block:: c static ssize_t myreader(struct file *fp, char __user *user_buffer, size_t count, loff_t *position) { return simple_read_from_buffer(user_buffer, count, position, ker_buf, len); } /* write file operation */ static ssize_t mywriter(struct file *fp, const char __user *user_buffer, size_t count, loff_t *position) { if (count > len) return -EINVAL; return simple_write_to_buffer(ker_buf, len, position, user_buffer, count); } static const struct file_operations fops_debug = { .read = myreader, .write = mywriter, }; .. _p3_debugfs_10: .. tab-set:: .. tab-item:: Mention the module init and exit function * Add the mention init and exit function which is executed the module is loaded and unloaded. .. code-block:: c module_init(init_debug); module_exit(exit_debug); .. _p3_debugfs_0: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: driver_debugfs.c .. literalinclude:: p3_debugfs/driver_debugfs.c :language: c :linenos: .. _p3_debugfs_1: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: p3_debugfs/Makefile :language: c :linenos: .. _p3_debugfs_2: .. tab-set:: .. tab-item:: Compile and Load * Run Make to compile the module. .. code-block:: shell $make make -C /lib/modules/5.4.0-150-generic/build M=$HOME/kernel_driver_debugfs modules make[1]: Entering directory '/usr/src/linux-headers-5.4.0-150-generic' CC [M] $HOME/kernel_driver_debugfs/driver_debugfs.o Building modules, stage 2. MODPOST 1 modules CC [M] $HOME/kernel_driver_debugfs/driver_debugfs.mod.o LD [M] $HOME/kernel_driver_debugfs/driver_debugfs.ko make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-150-generic' * Run ls to check if driver_debugfs.ko is generated or not. .. code-block:: shell $ ls -l total 36 -rw-rw-r-- 1 test test 154 Feb 26 13:18 Makefile -rw-rw-r-- 1 test test 47 Feb 26 13:18 modules.order -rw-rw-r-- 1 test test 0 Feb 26 13:18 Module.symvers -rw-rw-r-- 1 test test 820 Feb 26 13:18 driver_debugfs.c -rw-rw-r-- 1 test test 5880 Feb 26 13:18 driver_debugfs.ko -rw-rw-r-- 1 test test 47 Feb 26 13:18 driver_debugfs.mod -rw-rw-r-- 1 test test 919 Feb 26 13:18 driver_debugfs.mod.c -rw-rw-r-- 1 test test 3448 Feb 26 13:18 driver_debugfs.mod.o -rw-rw-r-- 1 test test 3320 Feb 26 13:18 driver_debugfs.o * Run insmod to load the module. .. code-block:: shell $ sudo insmod ./driver_debugfs.ko * Once the module is loaded into kernel check for the files created. .. code-block:: shell $ ls -l /sys/kernel/debug/dell/ total 0 -rw-r--r-- 1 root root 0 Jul 14 20:08 hexnum -rw-r--r-- 1 root root 0 Jul 14 20:08 number -rw-r--r-- 1 root root 0 Jul 14 20:08 text * Run rmmod to unload the module. .. code-block:: shell $ sudo rmmod driver_debugfs * Check dmesg and we can clearly see the read and write operations are executed. .. code-block:: shell [ 9523.186611] Device Driver Loaded.. [ 9534.912912] Device Driver Unloaded.. .. _p3_debugfs_3: .. tab-set:: .. tab-item:: Summary =============================== =============================================== API Learning =============================== =============================================== debugfs_create_dir To create a directory within /sys/kernel/debug debugfs_create_file To create a file in the above directory debugfs_create_u64 To create a file which takes in a int(64) value debugfs_remove_recursive To create a file which takes hex decimal value =============================== =============================================== .. card:: See Also * Previous Chapters * :doc:`../chapter1_basics/chapter1_basics` * :doc:`../chapter2_kthreads/chapter2_kthreads` * :doc:`../chapter3_tasklets/chapter3_tasklets` * :doc:`../chapter4_workqueue/chapter4_workqueue` * :doc:`../chapter5_timer/chapter5_timer` * :doc:`../chapter8_linkedList/chapter8_linkedList` * Other File System topics * :doc:`p1_sysfs` * :doc:`p2_procfs` * Next Chapter * :doc:`../chapter10_netlink/chapter10_netlink`