Linux用户与内核空间交互—debugfs

目录

简介

一、debugfs

API

二、程序源码

输出


简介

用户空间与内核的交互方式,使用copy_from_user(), copy_to_user().

除了这两种交互方式,内核还提供了其他高级的方式,对于写驱动来说很重要。有proc、sysfs、debugfs、netlink、ioctl。

本文学习debugfs

一、debugfs

在开发调试过程,通过输入cat file 文件命令,内核触发回调函数将所需要的信息提供给用户

内核配置:CONFIG_DEBUG_FS

查看是否已经挂载

# mount | grep -w debugfs
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime)

root@ubuntu:/sys/kernel/debug# ls
acpi   cleancache       device_component  dma_pools      error_injection     gpio          kprobes  pmc_core  regmap      sleep_time        sync     virtio-ports    zswap
bdi    clear_warn_once  devices_deferred  dri            extfrag             hid           mce      pm_genpd  regulator   split_huge_pages  tracing  vmmemctl
block  clk              dma_buf           dynamic_debug  fault_around_bytes  interconnect  opp      pwm       remoteproc  suspend_stats     ttm      wakeup_sources
cec    devfreq          dmaengine         energy_model   frontswap           iosf_sb       pinctrl  ras       sched       swiotlb           usb      x86

API

debugfs_create_dir  创建debugfs目录

debugfs_create_file 创建debugfs文件

debugfs_create_u32 自动创建内部回调函数,读写无符号32位数;其优点是不需要显示提供file_operations 结构体函数;

debugfs_create_bool 布尔类型的参数

debugfs_remove_recursive 删除文件,模块退出时没有调用此函数,继续访问debugfs文件,将引起oops错误。

二、程序源码

创建debugfs文件夹 dbgfs_simple_intf

创建两个文件,dbgfs_debug_level(显示一个值),dbgfs_show_drvctx(显示一组值)

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/uaccess.h>
#include <linux/sched/signal.h>

//debugfs文件
#define OURMODNAME      "dbgfs_simple_intf"

MODULE_AUTHOR("wy");
MODULE_LICENSE("Dual MIT/GPL");
MODULE_VERSION("0.1");

/* Module parameters */
static int cause_an_oops;
module_param(cause_an_oops, int, 0644);
MODULE_PARM_DESC(cause_an_oops,

//目录
static struct dentry *gparent;

//互斥体
DEFINE_MUTEX(mtx);

//参数结构体
struct drv_ctx {
	int tx, rx, err, myword, power;
	u32 config1;
	u32 config2;
	u64 config3; /* updated to the 'jiffies' value ... */
#define MAXBYTES   128
	char oursecret[MAXBYTES];
};
static struct drv_ctx *gdrvctx;
//debug_level参数
static int debug_level;		

//文件名
#define DBGFS_FILE2	"dbgfs_debug_level"
#define DBGFS_FILE1	"dbgfs_show_drvctx"

//当read函数触发时,自动调用此函数
static ssize_t dbgfs_show_drvctx(struct file *filp, char __user *ubuf,
				 size_t count, loff_t *fpos)
{
	struct drv_ctx *data = (struct drv_ctx *)filp->f_inode->i_private;
#define MAXUPASS 256	// 内核的栈非常小
	char locbuf[MAXUPASS];
    
	if (mutex_lock_interruptible(&mtx))
		return -ERESTARTSYS;
    //config参数值修改
	data->config3 = jiffies;
    //打包参数值
	snprintf(locbuf, MAXUPASS - 1,
		 "prodname:%s\n"
		 "tx:%d,rx:%d,err:%d,myword:%d,power:%d\n"
		 "config1:0x%x,config2:0x%x,config3:0x%llx (%llu)\n"
		 "oursecret:%s\n",
		 OURMODNAME,
		 data->tx, data->rx, data->err, data->myword, data->power,
		 data->config1, data->config2, data->config3, data->config3,
		 data->oursecret);

	mutex_unlock(&mtx);
    //将参数值传递给user,对copy_to_user的封装
	return simple_read_from_buffer(ubuf, MAXUPASS, fpos, locbuf,
				       strlen(locbuf));
}

//fops read方法
static const struct file_operations dbgfs_drvctx_fops = {
	.read = dbgfs_show_drvctx,
};

//结构体内存分配,并赋初始值
static struct drv_ctx *alloc_init_drvctx(void)
{
	struct drv_ctx *drvctx = NULL;

	drvctx = kzalloc(sizeof(struct drv_ctx), GFP_KERNEL);
	if (!drvctx)
		return ERR_PTR(-ENOMEM);
	drvctx->config1 = 0x0;
	drvctx->config2 = 0x48524a5f;
	drvctx->config3 = jiffies;
	drvctx->power = 1;
	strncpy(drvctx->oursecret, "AhA yyy", 8);

	pr_info("allocated and init the driver context structure\n");
	return drvctx;
}

//模块入口函数
static int __init debugfs_simple_intf_init(void)
{
	int stat = 0;
	struct dentry *file1, *file2;

    //检查是否开启debugfs
	if (!IS_ENABLED(CONFIG_DEBUG_FS)) {
		return -EINVAL;
	}

    //创建目录
	gparent = debugfs_create_dir(OURMODNAME, NULL);
	if (!gparent) {
		goto out_fail_1;
	}

    //创建ctx并赋初值
	gdrvctx = alloc_init_drvctx();
	if (IS_ERR(gdrvctx)) {
		goto out_fail_2;
	}

    //创建文件1
	file1 = debugfs_create_file(DBGFS_FILE1, 0440, gparent, (void *)gdrvctx, &dbgfs_drvctx_fops);
	if (!file1) {
		goto out_fail_3;
	}

    //创建文件2 创建的函数使用与第一个不同
    file2 = debugfs_create_u32(DBGFS_FILE2, 0644, gparent, &debug_level);
    if (!file2) {
        goto out_fail_3;
    }   
	return 0;

 out_fail_3:
	kfree(gdrvctx);
 out_fail_2:
	debugfs_remove_recursive(gparent);
 out_fail_1:
	return stat;
}

static void __exit debugfs_simple_intf_cleanup(void)
{
	kfree(gdrvctx);
	if (!cause_an_oops)//参数控制循环释放引起错误
		debugfs_remove_recursive(gparent);
}

module_init(debugfs_simple_intf_init);
module_exit(debugfs_simple_intf_cleanup);

输出

root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# ls -l
total 0
-rw-r--r-- 1 root root 0 Sep 30 01:37 dbgfs_debug_level
-r--r----- 1 root root 0 Sep 30 01:37 dbgfs_show_drvctx
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# cat dbgfs_show_drvctx 
prodname:dbgfs_simple_intf
tx:0,rx:0,err:0,myword:0,power:1
config1:0x0,config2:0x48524a5f,config3:0x10053c457 (4300457047)
oursecret:AhA yyy
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# 
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# 
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# 
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# cat dbgfs_debug_level 
0
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# echo 1 > dbgfs_debug_level 
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# cat dbgfs_debug_level 
1
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# echo 10 > dbgfs_debug_level 
root@ubuntu:/sys/kernel/debug/dbgfs_simple_intf# cat dbgfs_debug_level 
10

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux中,debugfs是一个用于调试和恢复文件系统的工具。它可以用来修复或恢复由于文件系统损坏或其他问题而导致的目录丢失。 以下是使用debugfs恢复目录的基本步骤: 1. 首先,确保你具有root权限或者以root用户身份登录。 2. 卸载目标文件系统:使用umount命令卸载目标文件系统。例如,如果目标文件系统位于/dev/sda1上,可以使用以下命令卸载它: ``` umount /dev/sda1 ``` 3. 打开debugfs:使用以下命令打开debugfs,并指定目标设备: ``` debugfs /dev/sda1 ``` 4. 使用ls命令查看文件系统中的目录结构。你应该能够看到所有的文件和目录。 5. 使用cd命令进入包含被删除目录的父目录。例如,如果目标目录的父目录是/lost+found,可以使用以下命令进入该目录: ``` cd /lost+found ``` 6. 使用mkdir命令创建一个新的目录。例如,如果你想恢复一个名为"recovered_directory"的目录,可以使用以下命令创建它: ``` mkdir recovered_directory ``` 7. 使用quit命令退出debugfs。 8. 挂载文件系统:使用mount命令重新挂载文件系统,让恢复的目录生效。例如,如果目标文件系统位于/dev/sda1上,可以使用以下命令重新挂载它: ``` mount /dev/sda1 /mnt ``` 现在,你应该能够在挂载的文件系统中看到恢复的目录。 请注意,使用debugfs进行文件系统恢复需要非常小心,并且需要对文件系统的结构和操作有一定的了解。确保在进行任何操作之前备份重要数据,并在不确定的情况下寻求专业人士的帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了维护世界和平_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值