Coding:小写一个debugfs

目录

事先检查

开干

撸代码


上一次整活还是在上一个月,写了一个简单的module并且熟悉了module的挂载查看和卸载。这一次我们自然玩一个大的,就是利用linux的debugfs API写一个调试文件系统。

事实上,底层的API全写好了,我们就是简单的调调API就成的事情!

事先检查

第一步是检查我们当前的内核是否支持debugfs调试:

zcat /proc/config.gz | grep DEBUG_FS
# CONFIG_XEN_DEBUG_FS is not set
CONFIG_BLK_DEBUG_FS=y
CONFIG_BLK_DEBUG_FS_ZONED=y
# CONFIG_SCSI_SNIC_DEBUG_FS is not set
# CONFIG_SCSI_LPFC_DEBUG_FS is not set
# CONFIG_USB_GADGET_DEBUG_FS is not set
# CONFIG_OCFS2_DEBUG_FS is not set
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_FS_ALLOW_ALL=y
# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set
# CONFIG_DEBUG_FS_ALLOW_NONE is not set

在这里,我们是要查看的是:CONFIG_DEBUG_FS=y,在这件事情上,如果是n,说明当前内核是不支持调试文件系统的,这就要求我们另外编译内核(打开这个开关),安装并进入内核才行。这里不再赘述如何自定义内核了。

开干

我们的文件系统有自己的一套fops,这里,也不是意外的。和我们对文件系统自身的认知,我们知道文件系统实际上就是提供一种对目标设备一套被抽象出来的访问读写等若干操作的句柄。所以我们所需要做的就是自己实现这一套句柄。显然我们需要实现的有打开文件 ,读文件以及写文件,这是最基本的!

我们的文件系统将会以模块的方式动态的加载到内核。所以这就要求我们需要先掌握学习如何编写模块的知识,这个在我之前的博客里有所提到。关于如何在Arch Linux上编写自己的第一个module_archlinux modules-CSDN博客

各位看官之前并没有了解到这方面的知识,可以阅读我上面所写的博客等掌握这个知识之后,再进行下一步的实践。

现在,我们沿用写模块的Makefile:

obj-m:= charlie.o
pwd:= $(shell pwd)
ker-ver:= $(shell uname -r)
KDIR:= /lib/modules/$(ker-ver)/build
# 下面这一行是用来调试的
# ccflags-y += -DDEBUG -g -ggdb -gdwarf-4 -Og \
                -Wall -fno-omit-frame-pointer -fvar-tracking-assignments
​
all:
    make -C $(KDIR) M=$(pwd) modules # 先调整一下目录,用人家的Makefile
​
clean:
    rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions *.order *.symvers *.mod写代码!

撸代码

我们首先需要引入写模块和调试文件系统的基本头文件。

#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/types.h>

然后完成读写,打开等基本操作。

static int charlie_fs_open(struct inode* inode, struct file* pfile)
{
// 函数是打开某一个文件,准备进行读或者写。
    printk("Charlie_filesystem_open\n");
    pfile->private_data = inode->i_private;
    return 0;
}
​
​
static ssize_t charlie_fs_read(struct file* pFile, char __user *buf, size_t cnt, loff_t* offp)
{
// 函数完成的任务是对传入进来的内存块进行存入buf里。
    int retval = 0;
    if((*offp + cnt) > 512)
        cnt = 512 - *offp;
// printk函数主要是向控制台打印一些控制信息,这个信息需要通过这条指令进行查看: sudo dmesg
    printk("Received read request! count:%ld, offset:%lld\n", cnt, *offp);
    if(copy_to_user(buf, charlie_buf + *offp, cnt)){
        // 警告!
        pr_warn("Oh no, failed to copy to user! count is %ld\n", cnt);
        retval = -EFAULT;
        goto out;
    }
    *offp += cnt;
    retval = cnt;
out:
    return retval; 
}
​
static ssize_t charlie_fs_write(struct file* pFile, const char __user *buf, size_t cnt, loff_t* offp)
{
// 函数完成的任务是向文件块进行写入。
    int retval;
    pr_info("Write request is here: count: %ld, offset:%lld\n", cnt, *offp);
    if(*offp > 512)
        return 0;
    if((*offp + cnt) > 512)
        cnt = 512 - *offp;
    if(copy_from_user(charlie_buf + *offp, (const void*)buf, cnt)){
        pr_warn("Oh no, failed to copy from user! count is %ld\n", cnt);
        retval = -EFAULT;
        goto out;
    }
    *offp += cnt;
    retval = cnt;
out:
    return retval; 
}

关于这里的几个所用到的函数都是什么意思,各位看官可自行百度更加详细的说明!

我们的文件系统是通过模块进行载入和卸载的,这就意味着我们仍然需要写初始化函数和析构函数。我们所做的就是要在初始化的时候完成对文件系统处理函数的注册。即在卸载文件系统的时候,移除我们在初始化时进行注册的相关函数。

// 句柄
struct file_operations charlie_fs_fops = {
    .owner = THIS_MODULE,
    .read = charlie_fs_read,
    .write = charlie_fs_write,
    .open = charlie_fs_open
};
​
​
// 模块的初始化
static int __init charlie_debug_fs_init(void)
{
    pr_info("The module is initing...");
    charlie_dir = debugfs_create_dir("Charliedir", NULL);
    if(!charlie_dir){
        pr_crit("Failing shit! can not create any dir at all!");
        goto failed;
    }
​
    static struct dentry* sub_charlie_dir;
    sub_charlie_dir =  debugfs_create_dir("CharlieSubDir", charlie_dir);
        if(!sub_charlie_dir){
        pr_crit("Failing shit! can not create any sub dir at all!");
        goto failed;
    }
​
    struct dentry* filent = debugfs_create_file("Charlie", 0644, sub_charlie_dir, NULL, &charlie_fs_fops);
    if(!filent){
        pr_err("Can not create file!");
        goto failed;
    }
    pr_info("Init finish!");
    return 0;
failed:
    return -ENOENT;
}
​
// 模块的析构函数
static void __exit charlie_debug_fs_exit(void)
{
    pr_info("Safe quit! begin");
    debugfs_remove_recursive(charlie_dir);
    pr_info("Safe quit! end");
}
​
module_init(charlie_debug_fs_init);
module_exit(charlie_debug_fs_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Charliechen");

到这里我们保存,然后make一下

make -C /lib/modules/6.9.7-arch1-1/build M=/home/Charliechen/Works/opearte_system/module/test2 modules
make[1]: Entering directory '/usr/lib/modules/6.9.7-arch1-1/build'
  CC [M]  /home/Charliechen/Works/opearte_system/module/test2/charlie.o
  MODPOST /home/Charliechen/Works/opearte_system/module/test2/Module.symvers
  CC [M]  /home/Charliechen/Works/opearte_system/module/test2/charlie.mod.o
  LD [M]  /home/Charliechen/Works/opearte_system/module/test2/charlie.ko
  BTF [M] /home/Charliechen/Works/opearte_system/module/test2/charlie.ko
make[1]: Leaving directory '/usr/lib/modules/6.9.7-arch1-1/build'
➜  sudo insmod charlie.ko && lsmod | grep charlie
[sudo] password for Charliechen: 
charlie                16384  0

看到我们的模块已经被正确的挂载!下一步,则是测试我们写的一系列功能。

➜  sudo ls /sys/kernel/debug/ | grep Charliedir
Charliedir
➜  sudo ls /sys/kernel/debug/Charliedir
CharlieSubDir
➜  sudo ls /sys/kernel/debug/Charliedir/CharlieSubDir
Charlie
➜  su
Password: 
[root@ArchLinux test2]# ls
charlie.c  charlie.ko  charlie.mod  charlie.mod.c  charlie.mod.o  charlie.o  Makefile  modules.order  Module.symvers
[root@ArchLinux test2]# sudo insmod charlie.ko && lsmod | grep charlie
charlie                16384  0
[root@ArchLinux test2]# echo 114514 > /sys/kernel/debug/Charliedir/CharlieSubDir/Charlie
[root@ArchLinux test2]# dmesg | tail -4
[18109.769088] The module is initing...
[18109.769097] Init finish!
[18117.722104] Charlie_filesystem_open
[18117.722177] Write request is here: count: 7, offset:0
[root@ArchLinux test2]# cat /sys/kernel/debug/Charliedir/CharlieSubDir/Charlie 
114514
​
[root@ArchLinux test2]# dmesg | tail -7
[18109.769088] The module is initing...
[18109.769097] Init finish!
[18117.722104] Charlie_filesystem_open
[18117.722177] Write request is here: count: 7, offset:0
[18147.692623] Charlie_filesystem_open
[18147.692645] Received read request! count:512, offset:0
[18147.692666] Received read request! count:0, offset:512
[root@ArchLinux test2]# rmmod charlie.ko
[root@ArchLinux test2]# dmesg | tail -8
[18109.769088] The module is initing...
[18109.769097] Init finish!
[18117.722104] Charlie_filesystem_open
[18117.722177] Write request is here: count: 7, offset:0
[18147.692623] Charlie_filesystem_open
[18147.692645] Received read request! count:512, offset:0
[18147.692666] Received read request! count:0, offset:512
[18165.395570] Safe quit! begin

完成!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/772642.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

欢乐钓鱼大师游戏攻略:在什么地方掉称号鱼?云手机游戏辅助!

《欢乐钓鱼大师》是一款融合了休闲娱乐和策略挑战的钓鱼游戏。游戏中的各种鱼类不仅各具特色&#xff0c;而且钓鱼过程充满了挑战和乐趣。下面将为大家详细介绍如何在游戏中钓鱼&#xff0c;以及一些有效的钓鱼技巧&#xff0c;帮助你成为一个出色的钓鱼大师。 实用工具推荐 为…

Day64 代码随想录打卡|回溯算法篇---组合总和

题目&#xff08;leecode T39&#xff09;&#xff1a; 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 …

什么开放式耳机好用?五大王牌开放式耳机种草!

随着科技的持续进步&#xff0c;开放式蓝牙耳机悄然兴起&#xff0c;逐步取代了经典的入耳式耳机。入耳式耳机以其卓越的隔音性能著称&#xff0c;然而&#xff0c;长时间的使用却容易引发耳道受压&#xff0c;伴随而来的不仅是疼痛与不适&#xff0c;更潜藏着耳膜受损的风险。…

90%的铲屎官必遇到家里猫毛满天飞问题,热门宠物空气净化器分享

作为一名资深猫奴&#xff0c;一到换毛季节家中就会忍受猫毛飞舞、异味四溢的双重困扰&#xff1f;花粉加上宠物的毛发和体味&#xff0c;过敏和不适似乎成了家常便饭。尝试过很多半方法&#xff0c;用过空气净化器去除毛和异味&#xff0c;虽然普通空气净化器可能提供一定程度…

swiftui中几个常用的手势控制单击点击,双击和长按事件

简单做了一个示例代码&#xff0c;包含三个圆形形状&#xff0c;配置了不同的事件&#xff0c;示例代码&#xff1a; // // RouterView.swift // SwiftBook // // Created by song on 2024/7/4. //import SwiftUIstruct RouterView: View {State var isClick falsevar bod…

Movable antenna 早期研究

原英文论文名字Historical Review of Fluid Antenna and Movable Antenna 最近&#xff0c;无线通信研究界对“流体天线”和“可移动天线”两种新兴天线技术的发展引起了极大的关注&#xff0c;这两种技术因其前所未有的灵活性和可重构性而极大地提高了无线应用中的系统性能。…

用Vue3和Plotly.js绘制交互式3D烛形图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 Plotly.js实现交互式K线图 应用场景 K线图广泛应用于金融领域&#xff0c;用于展示股票、外汇等金融产品的价格走势。它直观地呈现了开盘价、收盘价、最高价和最低价等信息&#xff0c;帮助投资者分析市场趋势…

“第六感”真的存在吗?

现在已有证据表明&#xff0c;人类除视觉、听觉、嗅觉、味觉和触觉五种感觉以外&#xff0c;确实存在“第六感” “第六感”的学术名称为“超感自知觉”(简称ESP)&#xff0c;它能透过正感官之外的渠道接收信息&#xff0c; 预知将要发生的事&#xff0c;而且与当事人之前的经…

探索Figma:下载流程及使用前准备

Figma 是基于浏览器的 UI 设计合作工具。无需下载&#xff0c;打开浏览器使用。虽然更建议直接在浏览器中使用 Figma&#xff0c;但是如果确实需要下载 Figma 客户端&#xff0c;可以直接在 Figma 官网的 Products > Downloads 页面下载。如果你不能访问 Figma 官网&#xf…

OpenWRT Patch 制作与使用

环境&#xff1a;Ubuntu 2404 Server, OpenWRT-23.05 quilt 首先安装 &#xff1a;sudo apt install quilt 为 Quilt - Summary [Savannah] 生成配置文件&#xff0c;使其适用于 OpenWRT。 ~/.quiltrc 针对当前用户&#xff0c;/etc/quilt.quiltrc 针对所有用户。这里选择 …

【LeetCode】十三、分治法:多数元素 + 最大子序列和

文章目录 1、分治法2、leetcode169&#xff1a;多数元素3、leetcode53&#xff1a;最大子序和 1、分治法 分治一般都搭配递归使用&#xff1a; 用分治法的一个应用——归并排序&#xff1a;将一组数不停的一分为二&#xff0c;直到分到每组只有一个数的时候 分到每组只有一个数…

【软件测试】Postman接口测试基本操作

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 Postman-获取验证码 需求&#xff1a;使用Postman访问验证码接口&#xff0c;并查看响应结果…

思看科技募资额骤降:对赌压力下巨额分红,还购买 7项商业房产

《港湾商业观察》施子夫 6月11日&#xff0c;证监会网站披露思看科技&#xff08;杭州&#xff09;股份有限公司&#xff08;以下简称&#xff0c;思看科技&#xff09;的首轮审核问询函回复意见并更新2023年财务数据&#xff0c;继续推进上市进程。 公开信息显示&#xff0c…

Logback日志配置两种方式

SpringBoot 默认使用的是Logback 1. 在resource新建文件logback-spring.xml&#xff0c;配置日志相关信息 <configuration><property name"app.name" value"order-service"/><property name"log.path" value"./logs/"…

鸿蒙小案例-首选项工具类

一个简单的首选项工具类 主要提供方法 初始化 init()方法建议在EntryAbility-》onWindowStageCreate 方法中使用 没多少东西&#xff0c;放一下测试代码 import { PrefUtil } from ./PrefUtil; import { promptAction } from kit.ArkUI;Entry Component struct PrefIndex {St…

强强联合!当RAG遇到长上下文,滑铁卢大学发布LongRAG,效果领先GPT-4 Turbo 50%

过犹不及——《论语先进》 大学考试时&#xff0c;有些老师允许带备cheet sheet&#xff08;忘纸条&#xff09;,上面记着关键公式和定义,帮助我们快速作答提高分数。传统的检索增强生成(RAG)方法也类似,试图找出精准的知识片段来辅助大语言模型(LLM)。 但这种方法其实有问题…

智能井盖采集装置 开启井下安全新篇章

在现代城市的脉络之下&#xff0c;错综复杂的管网系统如同城市的血管&#xff0c;默默支撑着日常生活的有序进行。而管网的监测设备大多都安装在井下&#xff0c;如何给设备供电一直是一个难题&#xff0c;选用市电供电需经过多方审批&#xff0c;选用电池供电需要更换电池包&a…

探索哈希函数:数据完整性的守护者

引言 银行在处理数以百万计的交易时&#xff0c;如何确保每一笔交易都没有出错&#xff1f;快递公司如何跟踪成千上万的包裹&#xff0c;确保每个包裹在运输过程中没有丢失或被替换&#xff1f;医院和诊所为庞大的患者提供有效的医疗保健服务&#xff0c;如何确保每个患者的医疗…

FPGA - 图像灰度化

一&#xff0c;灰度图像概念 灰度数字图像是每个像素只有一个采样颜色的图像。这类图像通常显示为从最暗黑色到最亮的白色的灰度&#xff0c;尽管理论上这个采样可以任何颜色的不同深浅&#xff0c;甚至可以是不同亮度上的不同颜色。灰度图像与黑白图像不同&#xff0c;在计算机…

Redis 7.x 系列【18】事务

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. 命令2.1 MULTI2.2 EXEC2.3 DISCARD2.4 WATCH2.5 UNWATCH 3. 事务中的错误4.…