Linux内核 -- 汇编结合ko案例之PMU获取周期技术

ARMv7汇编实现周期计数读取与清空

本文档详细描述了如何在ARMv7平台上使用汇编语言编写周期计数器读取与清空函数,如何在内核模块中导出这些函数供其他模块调用,以及如何使用Netlink接口供用户态程序进行调用。

1. 汇编函数实现

首先,编写汇编函数以实现周期计数器的读取与清空。创建文件cpu_cycle.S

.global clear_cycle_counter
.global get_cycle_count// 清空周期计数器
clear_cycle_counter:// 将0写入周期计数器寄存器MCR p15, 0, r0, c9, c12, 2MOV pc, lr// 获取周期计数
get_cycle_count:// 从周期计数器寄存器读取值MRC p15, 0, r0, c9, c13, 0MOV pc, lr

2. 内核模块实现

接下来,编写内核模块代码,以导出汇编函数并通过Netlink提供接口。创建文件cm_cpu_cycle.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <net/sock.h>#define NETLINK_USER 31// 声明汇编函数
extern void clear_cycle_counter(void);
extern unsigned int get_cycle_count(void);// 导出汇编函数
EXPORT_SYMBOL(clear_cycle_counter);
EXPORT_SYMBOL(get_cycle_count);static struct sock *nl_sk = NULL;static void nl_recv_msg(struct sk_buff *skb) {struct nlmsghdr *nlh;int pid;struct sk_buff *skb_out;int msg_size;char *msg = NULL;int res;nlh = (struct nlmsghdr*)skb->data;pid = nlh->nlmsg_pid; // 获取发送者的PIDif (strncmp((char*)nlmsg_data(nlh), "clear", 5) == 0) {clear_cycle_counter();msg = "Cycle counter cleared";} else if (strncmp((char*)nlmsg_data(nlh), "get", 3) == 0) {unsigned int cycle_count = get_cycle_count();msg_size = snprintf(NULL, 0, "Cycle count: %u", cycle_count);msg = kmalloc(msg_size + 1, GFP_KERNEL);snprintf(msg, msg_size + 1, "Cycle count: %u", cycle_count);} else {msg = "Invalid command";}msg_size = strlen(msg);skb_out = nlmsg_new(msg_size, 0);if (!skb_out) {pr_err("Failed to allocate new skb
");return;}nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);NETLINK_CB(skb_out).dst_group = 0;strncpy(nlmsg_data(nlh), msg, msg_size);res = nlmsg_unicast(nl_sk, skb_out, pid);if (res < 0)pr_err("Error while sending back to user
");if (msg && strncmp(msg, "Cycle count: ", 13) == 0)kfree(msg);
}static int __init cm_cpu_cycle_init(void) {struct netlink_kernel_cfg cfg = {.input = nl_recv_msg,};nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &cfg);if (!nl_sk) {pr_err("Error creating socket.
");return -10;}pr_info("cm_cpu_cycle module loaded.
");return 0;
}static void __exit cm_cpu_cycle_exit(void) {netlink_kernel_release(nl_sk);pr_info("cm_cpu_cycle module unloaded.
");
}module_init(cm_cpu_cycle_init);
module_exit(cm_cpu_cycle_exit);MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cycle Count Management Module");
MODULE_AUTHOR("Your Name");

3. Makefile

创建Makefile以编译内核模块:

obj-m += cm_cpu_cycle.o
cm_cpu_cycle-objs := cm_cpu_cycle_main.o cpu_cycle.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

4. 用户态程序

编写用户态程序,通过Netlink接口与内核模块通信。创建文件user_program.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>#define NETLINK_USER 31struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;void send_msg(const char *cmd) {nlh->nlmsg_len = NLMSG_SPACE(1024);nlh->nlmsg_pid = getpid();nlh->nlmsg_flags = 0;strcpy(NLMSG_DATA(nlh), cmd);iov.iov_base = (void *)nlh;iov.iov_len = nlh->nlmsg_len;msg.msg_name = (void *)&dest_addr;msg.msg_namelen = sizeof(dest_addr);msg.msg_iov = &iov;msg.msg_iovlen = 1;sendmsg(sock_fd, &msg, 0);recvmsg(sock_fd, &msg, 0);printf("Received message payload: %s
", (char *)NLMSG_DATA(nlh));
}int main() {sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);if (sock_fd < 0) {return -1;}memset(&src_addr, 0, sizeof(src_addr));src_addr.nl_family = AF_NETLINK;src_addr.nl_pid = getpid();bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.nl_family = AF_NETLINK;dest_addr.nl_pid = 0;   // For Linux Kerneldest_addr.nl_groups = 0; // unicastnlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(1024));memset(nlh, 0, NLMSG_SPACE(1024));// 发送清空周期计数器命令send_msg("clear");// 发送获取周期计数器值命令send_msg("get");close(sock_fd);return 0;
}

5. 编译与加载模块

编译内核模块:

make

加载内核模块:

sudo insmod cm_cpu_cycle.ko

运行用户态程序:

gcc user_program.c -o user_program
./user_program

卸载内核模块:

sudo rmmod cm_cpu_cycle

通过以上步骤,可以实现一个在内核态使用汇编语言编写的周期计数读取与清空功能,并通过Netlink接口供用户态程序进行调用的完整示例。

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

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

相关文章

Java OA系统邮件管理模块

## 使用Spring Boot和Hibernate开发OA系统邮件管理模块 使用Spring Boot和Hibernate开发一个OA系统的邮件管理模块。该模块将支持邮件发送、接收、存储、查找、分类、标签管理&#xff0c;以及附件的上传和接收。前端部分使用Thymeleaf模板引擎&#xff0c;数据库选择MySQL。 …

AI智能体的炒作与现实:GPT-4都撑不起,现实任务成功率不到15%

AI 智能体的宣传很好&#xff0c;现实不太妙。 随着大语言模型的不断进化与自我革新&#xff0c;性能、准确度、稳定性都有了大幅的提升&#xff0c;这已经被各个基准问题集验证过了。 但是&#xff0c;对于现有版本的 LLM 来说&#xff0c;它们的综合能力似乎并不能完全支撑得…

from PyQt5.QtChart import QChart ImportError: DLL load failed: 找不到指定的模块。

最近在开发pyqt5代码 在运行是遇到from PyQt5.QtChart import QChart ImportError: DLL load failed: 找不到指定的模块。问题&#xff0c; 估计是安装QChart安装没正确&#xff0c;可以更新下安装包&#xff0c; pip install PyQt5 --upgrade pip install PyQtChart --upgrade…

云原生技术峰会:引领智能算力时代的创新浪潮

云原生技术峰会&#xff1a;引领智能算力时代的创新浪潮 随着云计算技术的飞速发展和智能算力的不断提升&#xff0c;云原生架构已成为推动企业数字化转型的重要力量。近日&#xff0c;一场汇聚了业界顶尖专家和学者的云原生技术峰会成功举行&#xff0c;与会者共同探讨了云原…

【Linux】常用基本命令

wget网址用于直接从网上下载某个文件到服务器&#xff0c;当然也可以直接从网上先把东西下到本地然后用filezilla这个软件来传输到服务器上。 当遇到不会的命令时候&#xff0c;可以使用man “不会的命令”来查看这个命令的详细信息。比如我想要看看ls这个命令的详细用法&…

antd react tour 引导式访问组件解决ref获取不到的问题

我是用了Tab组件&#xff0c;tab分1,2,3步骤&#xff0c;直接用ref不对。所以我找了这种方式&#xff0c;使用原生获取dom const [ref1, setRef1] useState(null);const [ref2, setRef2] useState(null);const [ref3, setRef3] useState(null);const [open, setOpen] useSt…

nextjs-在页面之间的导航跳转

原文链接&#xff1a;https://nextjs.org/learn/dashboard-app/navigating-between-pages 01-nextjs起步02-css样式03-处理字体和图片04-创建layouts 和pages 页面更多 在上一章中&#xff0c;您创建了仪表板布局和页面。现在&#xff0c;让我们添加一些链接&#xff0c;允许…

canvas : Cannot read properties of null (reading ‘getContext‘)

获取 canvas 元素的 getContext 方法时&#xff0c;canvas 元素尚未正确绑定。可以通过确保在渲染 PDF 文件之前&#xff0c;canvas 元素已经正确挂载到 DOM 来解决这个问题。 解决方法 确保 pdfCanvas 引用已经绑定到正确的 DOM 元素。确保在渲染 PDF 文件时&#xff0c;can…

【模型】5分钟了解决策树是一个什么模型

本站原创文章&#xff0c;转载请说明来自《老饼讲解-机器学习》[www.bbbdata.com(https://www.bbbdata.com/ml) 决策树模型是机器学习中不可不学的模型之一&#xff0c;本文简单直接地快速讲解决策树是什么&#xff0c;如何实现。 一、决策树模型 决策树一般包括ID3决策树&am…

【JS问题】require相对路径引入模块

潜在问题 安全性问题&#xff1a;使用相对路径来引入模块可能会带来安全隐患&#xff0c;尤其是如果这段代码运行在客户端&#xff08;比如Node.js的Electron框架&#xff09;且相对路径可以被用户控制的情况下。恶意用户可能会尝试修改路径来访问不应该被访问的文件。 模块路…

记录一个笔误引发的bug导致生产环境报错,但是本地环境,测试环境运行正常

记录一个笔误引发的bug导致生产环境报错&#xff0c;但是本地环境&#xff0c;测试环境运行正常 因为headers请求头过长导致报错 在feign外调其他系统时候&#xff0c;是重新封装headers 问题在于 MultiValueMap 属于静态变量。这里讲userAgent的内容传递过去。是不断累加的…

Java 应用的部署和运维方法,包括 Tomcat、Docker 等

Java应用的部署和运维是一个复杂且多样的过程&#xff0c;包括从代码编写到应用上线&#xff0c;再到应用的持续维护和优化。 一、基于Tomcat的Java应用部署和运维 1. 环境准备 操作系统&#xff1a;选择适合运行Java和Tomcat的操作系统&#xff0c;常见的有Ubuntu、CentOS等…

如何遍历STL容器

在C中&#xff0c;遍历STL&#xff08;Standard Template Library&#xff09;容器通常可以通过多种方法来完成。以下是几种常用的遍历STL容器的方法&#xff1a; 1. 使用迭代器&#xff08;Iterator&#xff09; 迭代器是STL中用于遍历容器的主要工具。它们提供了一种通用方…

Qt项目天气预报(8) - 绘制温度曲线 + 回车搜索(最终篇)

全部内容在专栏&#xff1a; Qt项目 天气预报_mx_jun的博客-CSDN博客 目录 绘制温度曲线 事件过滤器在子控件上绘图 子控件下载事件过滤器 事件过滤器进行绘图 - eventFilter 画初步高温曲线 画初步低温曲线 效果演示 画低温曲线 画高温曲线 效果演示 按下回车搜索: …

【C++PCL】点云处理点云密度计算

作者:迅卓科技 简介:本人从事过多项点云项目,并且负责的项目均已得到好评! 公众号:迅卓科技,一个可以让您可以学习点云的好地方 重点:每个模块都有参数如何调试的讲解,即调试某个参数对结果的影响是什么,大家有问题可以评论哈,如果文章有错误的地方,欢迎来指出错误的…

收银系统源码-千呼新零售2.0【宠物、养生、大健康行业解决方案】

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物、中医养生、大健康等连锁店…

什么是 java 序列化,如何实现 java 序列化

Java序列化是将对象的状态转换为字节流的过程&#xff0c;这样对象的状态可以被存储在文件、数据库中&#xff0c;或者通过网络传输给另一个Java虚拟机&#xff08;JVM&#xff09;。反序列化是相反的过程&#xff0c;即从字节流中重建对象的状态。 为什么需要序列化&#xff…

Web渗透:文件上传漏洞

文件上传漏洞&#xff08;File Upload Vulnerability&#xff09;是网络安全中的一种常见漏洞&#xff0c;攻击者可以通过此漏洞将恶意文件上传到服务器&#xff0c;从而执行任意代码、覆盖重要文件、或进行其他恶意操作。这种漏洞可能带来严重的安全风险&#xff0c;包括数据泄…

Python里的类型list是什么?

在Python中&#xff0c;list&#xff08;列表&#xff09;是一种内置的数据类型&#xff0c;用于存储有序的元素集合。这些元素可以是任何数据类型&#xff08;整数、浮点数、字符串、其他列表等&#xff09;&#xff0c;并且它们不需要是同一种数据类型。 列表使用方括号 [] 表…

在 PMP 考试中,项目管理经验不足怎么办?

在项目管理的专业成长之路上&#xff0c;PMP认证如同一块里程碑&#xff0c;标志着从业者的专业水平达到了国际公认的标准。然而&#xff0c;对于那些项目管理经验尚浅的考生来说&#xff0c;这座里程碑似乎显得有些遥不可及。那么&#xff0c;在PMP考试准备中&#xff0c;项目…