#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/dcache.h>
struct dentry *test_dentry;
struct PrivateInfo {
int id;
char tmp[20];
};
static struct PrivateInfo info = {
.id = 25,
.tmp = "hello world",
};
int demo_open(struct inode *inode, struct file *file)
{
struct PrivateInfo *pInfo;
pr_info("%s, ===>\n", __func__);
file->private_data = inode->i_private;
if (IS_ERR_OR_NULL(file->private_data)) {
pr_err("%s, file->private_data invalid\n", __func__);
return -EFAULT;
}
pInfo = (struct PrivateInfo*)(file->private_data);
pr_info("%s, id %d, tmp %s\n", __func__, pInfo->id, pInfo->tmp);
pr_info("%s, <===\n", __func__);
return 0;
}
int demo_release(struct inode *inode, struct file *file)
{
struct PrivateInfo *pInfo;
pr_info("%s, ===>\n", __func__);
file->private_data = inode->i_private;
if (IS_ERR_OR_NULL(file->private_data)) {
pr_err("%s, file->private_data invalid\n", __func__);
return -EFAULT;
}
pInfo = (struct PrivateInfo*)(file->private_data);
pr_info("%s, id %d, tmp %s\n", __func__, pInfo->id, pInfo->tmp);
pr_info("%s, <===\n", __func__);
return 0;
}
static const struct file_operations demo_fops = {
.open = demo_open,
.release = demo_release,
};
static int __init my_demo_init(void)
{
pr_info("%s, ===>\n", __func__);
pr_info("%s, before debugfs create file\n", __func__);
// 这里一定是 (void *)&info
test_dentry = (struct dentry *)debugfs_create_file("debug_demo", 0666, NULL, (void *)&info, &demo_fops);
if (IS_ERR_OR_NULL(test_dentry)) {
pr_err("%s, debugfs create file failed\n", __func__);
} else {
pr_info("%s, debugfs create file success\n", __func__);
}
pr_info("%s, <===\n", __func__);
return 0;
}
static void my_demo_exit(void)
{
pr_info("%s, ===>\n", __func__);
if (IS_ERR_OR_NULL(test_dentry)) {
pr_err("%s, debugfs is invalid\n", __func__);
} else {
debugfs_remove(test_dentry);
test_dentry = NULL;
pr_info("%s, debugfs remove success\n", __func__);
}
pr_info("%s, <===\n", __func__);
}
module_init(my_demo_init);
module_exit(my_demo_exit);
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("kiss1994");
MODULE_DESCRIPTION ("debugfs");
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main() {
char *filename = "/sys/kernel/debug/debug_demo";
int fd = open(filename,O_RDWR);
if(fd<0){
perror("open fail \n");
return -1;
}
printf("open file %s success!\n", filename);
sleep(3);
close(fd);
printf("close file %s success!\n", filename);
return 0;
}
[ 4215.441563] my_demo_init, ===>
[ 4215.441568] my_demo_init, before debugfs create file
[ 4215.441595] my_demo_init, debugfs create file success
[ 4215.441596] my_demo_init, <===
[ 4471.569330] demo_open, ===>
[ 4471.569338] demo_open, id 25, tmp hello world
[ 4471.569340] demo_open, <===
[ 4474.570193] demo_release, ===>
[ 4474.570202] demo_release, id 25, tmp hello world
[ 4474.570204] demo_release, <===
[ 4489.417556] my_demo_exit, ===>
[ 4489.417725] my_demo_exit, debugfs remove success
[ 4489.417728] my_demo_exit, <===
//=======================================================
/**
* debugfs_create_file - create a file in the debugfs filesystem
* @name: a pointer to a string containing the name of the file to create.
* @mode: the permission that the file should have.
* @parent: a pointer to the parent dentry for this file. This should be a
* directory dentry if set. If this parameter is NULL, then the
* file will be created in the root of the debugfs filesystem.
* @data: a pointer to something that the caller will want to get to later
* on. The inode.i_private pointer will point to this value on
* the open() call.
* @fops: a pointer to a struct file_operations that should be used for
* this file.
*
* This is the basic "create a file" function for debugfs. It allows for a
* wide range of flexibility in creating a file, or a directory (if you want
* to create a directory, the debugfs_create_dir() function is
* recommended to be used instead.)
*
* This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned.
*
* If debugfs is not enabled in the kernel, the value -%ENODEV will be
* returned.
*/
struct dentry *debugfs_create_file(const char *name, umode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops)
{
return __debugfs_create_file(name, mode, parent, data,
fops ? &debugfs_full_proxy_file_operations :
&debugfs_noop_file_operations,
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file);
/**
* debugfs_remove - recursively removes a directory
* @dentry: a pointer to a the dentry of the directory to be removed. If this
* parameter is NULL or an error value, nothing will be done.
*
* This function recursively removes a directory tree in debugfs that
* was previously created with a call to another debugfs function
* (like debugfs_create_file() or variants thereof.)
*
* This function is required to be called in order for the file to be
* removed, no automatic cleanup of files will happen when a module is
* removed, you are responsible here.
*/
void debugfs_remove(struct dentry *dentry)
{
if (IS_ERR_OR_NULL(dentry))
return;
simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);
simple_recursive_removal(dentry, remove_one);
simple_release_fs(&debugfs_mount, &debugfs_mount_count);
}
EXPORT_SYMBOL_GPL(debugfs_remove);