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 dmesgprintk("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.oMODPOST /home/Charliechen/Works/opearte_system/module/test2/Module.symversCC [M]  /home/Charliechen/Works/opearte_system/module/test2/charlie.mod.oLD [M]  /home/Charliechen/Works/opearte_system/module/test2/charlie.koBTF [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.mzph.cn/news/866317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

arthas命令使用

dashboard(线程、内存等环境概览) jvm&#xff08;JVM相关信息概览&#xff09; 1、RUNTIME&#xff08;系统运行环境JVM相关信息&#xff0c;运行时长等&#xff09; 2、CLASS-LOADING&#xff08;类加载信息&#xff09; 3、 COMPILATION&#xff08;编译信息&#xff09; 4…

TimerManager和Timer

在RTSP服务器中需要一个定时器来定时发送音频帧和视频帧。音频帧每隔23ms发送一帧&#xff0c;视频帧每隔40ms发一帧。 因此需要两个定时器来定时发送&#xff0c;此时我们就需要用到一个TimerManager来管理Timer。 在TimerManager类中我们需要创建定时器文件描述符&#xff…

Qt 网络编程实战

一.获取主机的网络信息 需要添加network模块 QT core gui network主要涉及的类分析 QHostInfo类 QHostInfo::localHostName() 获取本地的主机名QHostInfo::fromName(const QString &) 获取指定主机的主机信息 addresses接口 QNetworkInterface类 QNetworkInterfac…

Python——面向对象编程(类和对象)2

目录 私有属性和私有方法 01.应用场景及定义方式 02.伪私有属性和私有方法 继承 1.1继承的概念、语法和特点 1.继承的语法&#xff1a; 2.专业术语&#xff1a; 3.继承的传递性 1.2方法的重写 1.覆盖父类的方法 2.对父类方法进行扩展 关于super 1.3 父类的私有属性和…

一天搞定Echarts可视化!(1)——伪类的学习

在下面的课程当中&#xff0c;伪类是经常被使用到的一项css技术。所以这我们先进行伪类的学习来作为本次Echarts课程的前置知识。 认识“&” 在css中&#xff0c;“&”符号通常用于选择器中&#xff0c;表示选择某个元素的子元素或特定状态下的元素。 伪类 :hover—…

PID与PPID

参考文章&#xff1a;https://blog.csdn.net/oh_coding/article/details/128865229 PID (process ID)&#xff1a; 进程PID是当操作系统运行进程时系统自动为其分配的标识符&#xff0c;具有唯一性&#xff0c;且为非零整数。一个PID只会标识一个进程。一旦被发放将会是终生标识…

机械拆装-基于Unity-装配功能的实现

目录 1. 装配场景的相机控制 2. 鼠标拖拽和旋转功能的实现 2.1 鼠标拖拽 2.2 物体旋转 3. 零件与装配位置的对应关系 4. 轴向装配的准备位置 5. 装配顺序的实现 5.1 标签提示 5.2 定义一个变量记录步骤数值 1. 装配场景的相机控制 开始装配功能时&#xff0c;需要将相机调…

在大型项目中,怎样有效地组织和管理 SCSS 文件结构以提高开发效率?

在大型项目中&#xff0c;组织和管理 SCSS 文件结构是非常重要的&#xff0c;可以提高开发效率和代码的可维护性。下面是一些有效的方法&#xff1a; 使用模块化和层次化的文件结构&#xff1a;将 SCSS 文件按照模块进行组织&#xff0c;每个模块包含相关的样式规则。可以使用文…

vector与list的简单介绍

1. 标准库中的vector类的介绍&#xff1a; vector是表示大小可以变化的数组的序列容器。 就像数组一样&#xff0c;vector对其元素使用连续的存储位置&#xff0c;这意味着也可以使用指向其元素的常规指针上的偏移量来访问其元素&#xff0c;并且与数组中的元素一样高效。但与数…

1975react社区问答管理系统开发mysql数据库web结构node.js编程计算机网页源码

一、源码特点 react 社区问答管理系统是一套完善的完整信息管理类型系统&#xff0c;结合react.js框架和node.js后端完成本系统&#xff0c;对理解react node编程开发语言有帮助系统采用node框架&#xff08;前后端分离&#xff09;&#xff09;&#xff0c;系统具有完整的源…

【代码随想录训练营】【Day 63】【单调栈-2】| Leetcode 42, 84

【代码随想录训练营】【Day 63】【单调栈-2】| Leetcode 42, 84 需强化知识点 单调栈强化 题目 42. 接雨水 注意 python 数组反序用法 result [::-1] class Solution:def trap(self, height: List[int]) -> int:# n len(height)# leftMax, rightMax [0] * n, [0] * …

golang 垃圾回收

gc不回收什么 GC 不负责回收栈中的内存栈是一块专用内存&#xff0c;专门为了函数执行而准备的&#xff0c;存储着函数中的局部变量以及调用栈栈中的数据可以通过简单的编译器指令自动清理&#xff0c;也就不需要通过 GC 来回收了 垃圾回收算法 主流的两类垃圾回收算法有两种&a…

Spring Boot中的安全漏洞防护

Spring Boot中的安全漏洞防护 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot应用中有效防护安全漏洞。随着软件应用程序的复杂…

6种ETL计算引擎介绍

目录 一、ETL计算引擎定义 二、ETL计算引擎的功能和特性 三、6种ETL计算引擎 1、MapReduce 2、Tez 3、Spark 4、Flink 5、ClickHouse 6、Doris 一、ETL计算引擎定义 ETL&#xff08;Extract, Transform, Load&#xff09;计算引擎是用于执行ETL过程中数据转换阶段的关键组件之一…

mac如何压缩视频大小不改变画质,mac怎么压缩视频软件

在数字时代&#xff0c;视频已成为信息传递和娱乐消遣的重要媒介。然而&#xff0c;视频带来的愉悦体验背后&#xff0c;是日益增长的存储和分享压力。大视频文件不仅占用大量存储空间&#xff0c;上传和下载也变得异常缓慢。那么&#xff0c;如何才能有效压缩视频&#xff0c;…

ERROR: No matching distribution found for numpy

1.原因&#xff1a; 出现这两行英文是因为原先输入pip install numpy的方式不安全&#xff0c;不被信任所以无法下载。 2.解决方法&#xff1a; 改成以下命令执行&#xff1a; pip install numpy -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun…

2025年中国国际新能源汽车技术零部件及服务展览会

中国国际新能源汽车技术零部件及服务展览会&#xff0c;从设计到制造、从使用到服务&#xff0c;精准“链”接新能源汽车全产业链的技术供应商和汽车制造商&#xff0c;专业面向新能源造车供应链的行业盛会。2024展会回顾&#xff1a;在展会的3天里&#xff0c;有62家车企核心供…

共享拼购:创新商业模式引领小用户基数下的销售奇迹“

在瞬息万变的商业蓝海中&#xff0c;一个新颖且深具潜力的策略正悄然改变着游戏规则&#xff0c;它巧妙地避开了传统路径的束缚&#xff0c;以微妙却深远的调整&#xff0c;开辟出了一条通往成功的独特航道。我的一位合作伙伴&#xff0c;正是这一策略的实践者&#xff0c;他在…

数据库设计(实战项目)-1个手机号多用户身份

一. 背景&#xff1a; 该需求是一个互联网医院的预约单场景&#xff0c;护士在小程序上申请患者查房预约单&#xff0c;医生在小程序上对预约单进行接单&#xff0c;护士开始查房后填写查房小结&#xff0c;客户需要对用户信息进行授权&#xff0c;医生查房后进行签字&#xff…

数字媒体技术基础之:DNG 文件

DNG&#xff08;Digital Negative&#xff09;文件是一种用于存储原始图像数据的文件格式&#xff0c;由 Adobe Systems 于2004年开发并推广。DNG 是一种开放的、非专利的原始图像格式&#xff0c;旨在为不同相机制造商提供一个统一的存储格式。DNG 文件保存了原始的、未处理的…