Linux内核开发-编写一个proc文件

0.前言

上一章(点击返回上一章)完成了一个内核模块的编写,实现了在内核运行时的动态加载和卸载。
在模块的开发调测过程中或者模块运行过程中,可能需要打印内核模块的变量的值或者想要动态开关模块的运行日志打印,那么就需要一个与内核交互的接口来实现这个目的。

1.什么是/proc文件

proc 文件系统是一个虚拟文件系统(类似的还有sys文件系统),对内核模块中的全局变量,我们都可以为其生成一个/proc文件,在控制台(即应用层)对其进行读写操作。

2.编写一个/proc文件

需求:某个模块在客户现场出问题了,需要记录内核模块的日志用于记录运行情况。
分析:在函数被调用不频繁的情况下,可以直接使用printk来打印函数运行的分支情况。但是printk操作很消耗性能,在会产生大量打印的情况下,很可能会由于一直在print,cpu得不到调度而出发系统重启。因此需要实现一个能根据需求动态调整打印的方式。

if (debug_enable)
{printk("[%s:%d], come here\n", __func__, __LINE__);
}

如上的代码片段,我们只要能控制debug_enable这个变量就能控制日志打印的输出。

2.1 代码实现

2.1.1 km_proc文件

一般开发中,会有多个proc文件创建的需求,对于这些创建、读、写逻辑都统一放到一个文件中进行,本项目就放在km_proc.c和km_proc.h中,其中最重要的km_proc.c文件内容如下:

#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/version.h>
#include "km_proc.h"/* 我们本次就是为此变量创建一个proc文件,并在控制台读写它 */
extern int km_debug_enable;struct proc_dir_entry *km_proc_dir = NULL;         /* km模块文件夹,用于存放模块的所有proc文件 */
struct proc_dir_entry *km_debug_proc_file = NULL;  /* km_debug对应的proc文件 */static int km_debug_proc_show(struct seq_file* file, void* v)
{seq_printf(file, "km_debug_enable:%d\n", km_debug_enable);return 0;
}static int km_debug_proc_open(struct inode* inode, struct file* file)
{return single_open(file, km_debug_proc_show, NULL);
}static ssize_t km_debug_proc_write(struct file* file, const char __user *buffer, size_t count, loff_t *pos)
{char buf[2] = {0};if (count > 2){printk("error:please input 0 or 1");return -ENOSPC;}if (copy_from_user(buf, buffer, count)){return -EFAULT;}sscanf(buf, "%d", &km_debug_enable);printk("km_debug_enable:%d\n", km_debug_enable);return count;
}#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
static const struct proc_ops km_debug_proc_fops = {.proc_open = km_debug_proc_open,.proc_read = seq_read,.proc_release = single_release,.proc_write = km_debug_proc_write,
};
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
static const struct file_operations km_debug_proc_fops = {.owner = THIS_MODULE,.open = km_debug_proc_open,.read = seq_read,.release = single_release,.write = km_debug_proc_write,
};
#else
#error "Please make sure your kernel vision" /* proc文件相关结构体和接口与内核版本有关,需要单独适配 */
#endifint km_init_proc(void)
{int ret = 0;/* 创建/proc/km文件夹 */km_proc_dir = proc_mkdir(KM_PROC_DIR, NULL);if (NULL == km_proc_dir) /* 创建失败,退出 */{ret = -1;printk("proc_mkdir fail!\n");goto err;}/* 创建/proc/km/km_debug文件 */km_debug_proc_file = proc_create(KM_DEBUG_FILE, 0644, km_proc_dir, &km_debug_proc_fops);if (NULL == km_debug_proc_file){ret = -1;printk("create /proc/%s/%s fail!\n", KM_PROC_DIR, KM_DEBUG_FILE);goto err1;}printk("proc init success!\n");return ret;err1:/* 失败,销毁已经创建的文件 */remove_proc_entry(KM_PROC_DIR, NULL);
err:return ret;
}void km_exit_proc(void)
{/* 按反向顺序一个个销毁,即先销毁文件、再销毁文件夹 */if (km_debug_proc_file){remove_proc_entry(KM_DEBUG_FILE, km_proc_dir);km_debug_proc_file = NULL;}if (km_proc_dir){remove_proc_entry(KM_PROC_DIR, NULL);km_proc_dir = NULL;}printk("proc exit complete!\n");
}

其余变更见:github:kernel_module:为自己的内核模块添加一个proc文件

2.2.2 编译、运行、测试

# 源码目录下编译
make# 插入模块
insmod km.ko# 查看插入结果
lsmod

查看内核打印信息:

dmesg

可以看到:
在这里插入图片描述
查看变量km_debug_enable的值:

cat /proc/km/km_debug

输出:
在这里插入图片描述
修改变量km_debug_enable的值:

sudo sh -c "echo 1 > /proc/km/km_debug"

在这里插入图片描述
可以看到修改已经生效了。
注意:修改km_debug_enable值时,如果直接输入echo,会提示权限不够,原因可见:https://blog.csdn.net/change_can/article/details/115128218

3. 其他

在上面代码中,可以看到有如下的条件编译指令:

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)#else
#error "Please make sure your kernel vision" /* proc文件相关结构体和接口与内核版本有关,需要单独适配 */
#endif

在实际开发中,一份代码可能需要运行在各种机器上,机器使用的内核版本有差异,而不同的内核版本各个接口、结构体定义可能会有差异,这时候就可以用这种条件编译指令通过判断内核版本来编译不同的代码分支,减小代码维护的复杂度。

4.下一章:待计划

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

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

相关文章

小盒子跑大模型!基于算能BM1684X+FPGA平台实现大模型私有化部署

当前&#xff0c;在人工智能领域&#xff0c;大模型在丰富人工智能应用场景中扮演着重要的角色&#xff0c;经过不断的探索&#xff0c;大模型进入到落地的阶段。而大模型在落地过程中面临两大关键难题&#xff1a;对庞大计算资源的需求和对数据隐私与安全的考量。为应对这些挑…

springcloud-gateway include-expression 配置说明

在开发过程中遇到的一些配置问题&#xff0c;记录下来以供参考 spring-gateway版本是2.2.9-release,使用的spring cloud dependence 是 Hoxton.SR12 在依赖eureka 服务发现并自动将发现服务器加入到router中的时候&#xff0c;需要指定对应的服务进行添加&#xff0c;根据文档…

postman国内外竞争者及使用详解分析

一、postman简介 Postman 是一款广泛使用的 API 开发和测试工具&#xff0c;适用于开发人员和测试人员。它提供了一个直观的界面&#xff0c;用于发送 HTTP 请求、查看响应、创建和管理 API 测试用例&#xff0c;以及自动化 API 测试工作流程。以下是 Postman 的主要功能和特点…

linux的CP指令

实现 CP 指令 src 源文件 des 目标文件 执行流程&#xff1a; 打开源文件&#xff08; src &#xff09; open 打开目标文件&#xff08; des &#xff09; open 写入目标文件 write 读取 src 文件到缓存数组 read 关闭目标文件和源文件 close ./a.out src.c de…

开源网安参与编制的《代码大模型安全风险防范能力要求及评估方法》正式发布

​代码大模型在代码生成、代码翻译、代码补全、错误定位与修复、自动化测试等方面为研发人员带来了极大便利的同时&#xff0c;也带来了对安全风险防范能力的挑战。基于此&#xff0c;中国信通院依托中国人工智能产业发展联盟&#xff08;AIIA&#xff09;&#xff0c;联合开源…

Mybatis-plus学习|性能分析插件、条件构造器、代码自动生成器

性能分析插件 我们在平时的开发中&#xff0c;会遇到一些慢sql。测试!druid…. MP也提供性能分析插件&#xff0c;如果超过这个时间就停止运行! 1、导入插件 该插件只允许在开发和测试环境中使用&#xff0c;故先设置开发环境为开发模式 在MP配置类中注册这个插件&#xff0…

Python:浅谈迭代器、生成器与协程的演化路径

“人生苦短&#xff0c;我用Python”&#xff0c;虽然说大量数学和统计分析库是一个重要优势&#xff0c;但是归根结底&#xff0c;Python的最大优势就是三点&#xff1a; 但是通常一般来讲&#xff0c;当扯到并发的时候&#xff0c;无论是多服务器、多进程、多线程、还是协程&…

C# SocketUDP服务器,组播

SocketUDP 自己即是服务器又是客户端 &#xff0c;在发消息只需要改成对方ip和端口号即可 前提对方必须开启服务器 socket.Bind(new IPEndPoint(IPAddress.Parse("192.168.107.72"), 8080)); 控件&#xff1a;Button,TextBox,RichTextBox 打开自己服务器 public…

【操作系统】信号处理与阻塞函数|时序竞态问题

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 ​ 关于阻塞函数和…

Windows环境部署MySQL_8.4.0 LTS的部署安装、验证连接以及卸载全过程实操手册

前言&#xff1a; 什么是 MySQL MySQL 是一个关系型数据库管理系统&#xff0c;由瑞典 MySQL AB 公司开发&#xff0c;目前属于Oracle 公司。MySQL 是一种关系型数据库管理系统&#xff0c;关系型数据库将数据保存在不同的表中&#xff0c;而不是将所有数据放在一个大仓库内&am…

8.12 矢量图层面要素单一符号使用七(随机标记填充)

文章目录 前言随机标记填充&#xff08;Random Marker Fill&#xff09;QGis设置面符号为随机标记填充&#xff08;Random Marker Fill&#xff09;二次开发代码实现随机标记填充&#xff08;Random Marker Fill&#xff09; 总结 前言 本章介绍矢量图层线要素单一符号中使用随…

分班查询怎么发布?

在现代教育环境中&#xff0c;传统的学生分班通知方式可能显得有些过时和低效。通常&#xff0c;这些方式依赖于纸质通知单&#xff0c;这不仅需要大量的物理资源进行打印和分发&#xff0c;而且容易出错&#xff0c;如丢失、错误分发或延迟。 幸运的是&#xff0c;现在有了更高…

心灵馆咨询系统小程序心理咨询平台聊天咨询

心灵馆咨询系统小程序&#xff1a;解锁你的心灵密码 &#x1f496; 心灵之旅的导航者 在繁忙的现代生活中&#xff0c;我们时常会面临各种压力与困惑。心灵馆咨询系统小程序&#xff0c;如同一位贴心的导航者&#xff0c;引领我们探索内心的世界&#xff0c;寻找真正的自我。 …

shell 脚本的部分指令和操作符

终端输入两个数&#xff0c;判断两数是否相等&#xff0c;如果不相等&#xff0c;判断大小关系 2.已知网址www.hqyj.com&#xff0c;使用expr截取出www、hqyj、com&#xff0c;不能使用cut&#xff0c;不能出现数字

JavaWeb系列十九: jQuery的DOM操作 上

查找节点, 修改属性 查找属性节点: 查找到所需要的元素之后, 可以调用jQuery对象的attr()方法用来 设置/返回 它的各种属性值 设置属性值 $(“img”).attr(“width”, “300”);返回属性值 $(“img”).attr(“width”); 创建节点 创建节点: 使用jQuery的工厂函数$(): $(html标…

硬核实力再亮,玩出梦想科技发布全球首款安卓系统空间计算机

6月25日&#xff0c;玩出梦想科技在新加坡召开全球新品发布会&#xff0c;正式发布全球首款安卓系统空间计算机——玩出梦想MR&#xff0c;填补了空间计算机在安卓生态的空白。 作为品牌沉淀两年的破晓之作&#xff0c;玩出梦想MR以业内领先软硬件配置&#xff0c;强大自研算法…

解决了!暗影精灵8 Pro酷睿版无声音,扬声器和麦克风都没有声音!

困扰好几天的问题解决了&#xff01; 暗影精灵8 Pro酷睿版无声音&#xff0c;扬声器和麦克风都没有声音&#xff01;&#xff01;方法适用于OMEN by HP Gaming Laptop 16-k0xxx&#xff08;暗影精灵8 Pro酷睿版&#xff09;的Windows 10声卡驱动&#xff01; 朋友们&#xff…

【应用开发一】LED开发

文章目录 1应用层控制外设的两种方式2 sysfs和/sys关系3 LED控制方式3.1 基本情况3.2 LED属性文件介绍3.3 命令行属性测试3.4 led程序3.5 开发板上测试 1应用层控制外设的两种方式 使用设备文件控制 在Linux系统下&#xff0c;一切皆是文件。应用层控制底层硬件同样也是通过文…

第100+12步 ChatGPT学习:R实现KNN分类

基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言&#xff0c;不想学Python咯。 答曰&#xff1a;可&#xff01;用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了&#xff0c;就帮各位搬运一下吧。 二、R代码实现KNN分类 &#xff08;1&a…