IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux用户与内核空间交互—debugfs -> 正文阅读

[系统运维]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


参考:

https://course.0voice.com/v1/course/intro?courseId=2&agentId=0

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 21:17:28  更:2022-10-08 21:18:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:34:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码