Linux内核 -- 汇编结合ko案例之PMU获取cpu cycle技术
ARMv7汇编实现周期计数读取与清空
本文档详细描述了如何在ARMv7平台上使用汇编语言编写周期计数器读取与清空函数,如何在内核模块中导出这些函数供其他模块调用,以及如何使用Netlink接口供用户态程序进行调用。
1. 汇编函数实现
首先,编写汇编函数以实现周期计数器的读取与清空。创建文件cpu_cycle.S:
.global clear_cycle_counter
.global get_cycle_count
.global select_cycle_counter
.global cm_enable_pmu// 开启PMU功能
cm_enable_pmu:MRC p15, 0, r0, c9, c12, 0 // 读取 PMU_CTRL寄存器值到R0ORR r0, r0, #1MCR p15, 0, r0, c9, c12, 0 // 将R0的值写入PMU_CTRL寄存器值// 清空周期计数器
clear_cycle_counter:// 将0写入周期计数器寄存器MCR p15, 0, r0, c9, c13, 2MOV pc, lr// 获取周期计数
get_cycle_count:// 从周期计数器寄存器读取值MRC p15, 0, r0, c9, c13, 2MOV pc, lrselect_cycle_counter://选择周期计数器 如nt98528是0~5// 选择0号计数器MOV r0, #0MCR p15, 0, r0, c9, c12, 5MOV 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接口供用户态程序进行调用的完整示例。
相关文章:
Linux内核 -- 汇编结合ko案例之PMU获取cpu cycle技术
ARMv7汇编实现周期计数读取与清空 本文档详细描述了如何在ARMv7平台上使用汇编语言编写周期计数器读取与清空函数,如何在内核模块中导出这些函数供其他模块调用,以及如何使用Netlink接口供用户态程序进行调用。 1. 汇编函数实现 首先,编写…...
探索 Symfony 框架:工作原理、特点及技术选型
目录 1. 概述 2. Symfony 的工作原理 2.1 MVC 架构 2.2 前端控制器模式 2.3 路由机制 2.4 依赖注入容器 2.5 事件驱动架构 3. Symfony 的特点 3.1 高度可扩展性 3.2 强大的社区支持和生态系统 3.3 优秀的性能和可伸缩性 3.4 严格的代码规范和最佳实践 4. Symfony …...
从万里长城防御体系看软件安全体系建设@安全历史03
长城,是中华民族的一张重要名片,是中华民族坚韧不屈、自强不息的精神象征,被联合国教科文组织列入世界文化遗产名录。那么在古代,长城是如何以其复杂的防御体系,一次次抵御外族入侵,而这些防御体系又能给软…...
ISO 19110操作要求类中的/req/operation/formal-definition详细解释
/req/operation/formal-definition 要求: 每个要素操作实体必须具有一个形式定义(formal definition),该定义应明确描述操作的行为和影响。 具体解释 定义 要素操作实体(feature operation entity):这…...
豆包大语言模型API调用错误码一览表
本文介绍了您可能从 API 和官方 SDK 中看到的错误代码。 http code说明 400 原因:错误的请求,例如缺少必要参数,或者参数不符合规范等 解决方法:检查请求后重试 401 原因:认证错误,代表服务无法对请求进…...
AI辅助设计:如何通过机器学习革新创意工作流程
🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主 📌 擅长领域:全栈工程师、爬虫、ACM算法,大数据,深度学习 💒 公众号…...
轻松解锁电脑强悍性能,4000MHz的玖合星舞 DDR4 内存很能打
轻松解锁电脑强悍性能,4000MHz的玖合星舞 DDR4 内存很能打 哈喽小伙伴们好,我是Stark-C~ 很多有经验的电脑玩家在自己DIY电脑选购内存条的时候,除了内存总容量,最看重的参数那就是频率了。内存频率和我们常说的CPU主频一样&…...
SpringBoot | 使用jwt令牌实现登录认证,使用Md5加密实现注册
对于登录认证中的令牌,其实就是一段字符串,那为什么要那么麻烦去用jwt令牌?其实对于登录这个业务,在平常我们实现这个功能时,可能大部分都是通过比对用户名和密码,只要正确,就登录成功ÿ…...
Springboot基于Redis的高性能分布式缓存数据库的实现与实例
一、引言 在现代的分布式系统和高并发应用中,缓存机制显得尤为重要。Redis作为一种开源(BSD许可)的内存键值存储,因其高性能、丰富的数据结构和多样化的应用场景,成为开发者们的首选。在这篇博客中,我们将…...
防止多次点击,vue的按钮上做简易的防抖节流处理
话不多说,上个视频,看看是不是你要的效果 防抖节流 1.创建一个directive.js // directive.js export default {install(Vue) {// 防重复点击(指令实现)Vue.directive(repeatClick, {inserted(el, binding) {el.addEventListener(click, () > {if (!el.disabled) {el.disabl…...
云计算【第一阶段(21)】Linux引导过程与服务控制
目录 一、linux操作系统引导过程 1.1、开机自检 1.2、MBR引导 1.3、GRUB菜单 1.4、加载 Linux 内核 1.5、init进程初始化 1.6、简述总结 1.7、初始化进程centos 6和7的区别 二、排除启动类故障 2.1、修复MBR扇区故障 2.1.1、 实验 2.2、修复grub引导故障 2.2.1、实…...
Google 发布最新开放大语言模型 Gemma 2,现已登陆 Hugging Face Hub
Google 发布了最新的开放大语言模型 Gemma 2,我们非常高兴与 Google 合作,确保其在 Hugging Face 生态系统中的最佳集成。你可以在 Hub 上找到 4 个开源模型 (2 个基础模型和 2 个微调模型) 。发布的功能和集成包括: Hub 上的模型https://hf.…...
智能分析赋能等保:大数据技术在安全审计记录中的应用
随着信息技术的飞速发展,大数据技术在各行各业中的应用愈发广泛,特别是在网络安全领域,大数据技术为安全审计记录提供了强有力的支撑。本文将深入探讨智能分析如何赋能等保(等级保护),以及大数据技术在安全…...
Django中,update_or_create()
在Django中,可以使用update_or_create()方法来更新现有记录或创建新记录。该方法接受一个字典作为参数,用于指定要更新或创建的字段和对应的值。 update_or_create()方法的语法如下: 代码语言:python obj, created Model.obje…...
每日一学(1)
目录 1、ConCurrentHashMap为什么不允许key为null? 2、ThreadLocal会出现内存泄露吗? 3、AQS理解 4、lock 和 synchronized的区别 1、ConCurrentHashMap为什么不允许key为null? 底层 putVal方法 中 如果key || value为空 抛出…...
SpringMVC(1)——入门程序+流程分析
MVC都是哪三层?在Spring里面分别对应什么?SpringMVC的架构是什么? 我们使用Spring开发JavaWeb项目,一般都是BS架构,也就是Browser(浏览器)-Server(服务器)架构 这种架构…...
成绩发布背后:老师的无奈与痛点
在教育的广阔天地里,教师这一角色承载着无数的期望与责任。他们不仅是知识的传播者,更是学生心灵的引路人。而对于班主任老师来说,他们的角色更加多元,他们不仅是老师,还必须是“妈妈”。除了像其他老师一样备课、上课…...
MySQL 索引之外的相关查询优化总结
在这之前先说明几个概念: 1、驱动表和被驱动表:驱动表是主表,被驱动表是从表、非驱动表。驱动表和被驱动表并非根据 from 后面表名的先后顺序而确定,而是根据 explain 语句查询得到的顺序确定;展示在前面的是驱动表&am…...
EE trade:贵金属投资的优点及缺点
贵金属(如黄金、白银、铂金和钯金)一直以来都是重要的投资和避险工具。它们具有独特的物理和化学特性,广泛应用于各种行业,同时也被视为财富储备。在进行贵金属投资时,了解其优点和缺点对于做出明智的投资决策至关重要。 一、贵金属投资的优…...
python工作目录与文件目录
工作目录 文件目录:文件所在的目录 工作目录:执行python命令所在的目录 D:. | main.py | ---data | data.txt | ---model | | model.py | | train.py | | __init__.py | | | ---nlp | | | bert.py | …...
零基础玩转像素幻梦:快速生成《光纹苔藓姑苏幻梦》同款像素画
零基础玩转像素幻梦:快速生成《光纹苔藓姑苏幻梦》同款像素画 1. 像素幻梦初体验 1.1 什么是像素幻梦创意工坊 像素幻梦创意工坊(Pixel Dream Workshop)是一款基于FLUX.1-dev扩散模型构建的AI像素艺术生成工具。它采用明亮的16-bit像素风格…...
OpenClaw网关配置详解:Qwen3-32B镜像的端口与安全设置
OpenClaw网关配置详解:Qwen3-32B镜像的端口与安全设置 1. 为什么需要关注网关配置? 上周我在本地部署Qwen3-32B模型时,遇到了一个尴尬的问题:凌晨3点被安全团队电话叫醒,原因是OpenClaw的测试端口被扫描到异常流量。…...
本地数据库工具革新:浏览器应用如何3分钟解决SQLite查看难题
本地数据库工具革新:浏览器应用如何3分钟解决SQLite查看难题 【免费下载链接】sqlite-viewer View SQLite file online 项目地址: https://gitcode.com/gh_mirrors/sq/sqlite-viewer 在数字化开发的日常工作流中,SQLite数据库文件查看往往成为效率…...
GLM-OCR Python API详解:predict接口返回结构、置信度阈值设置与后处理
GLM-OCR Python API详解:predict接口返回结构、置信度阈值设置与后处理 1. 项目概述与环境准备 GLM-OCR 是一个基于先进多模态架构的高性能OCR识别模型,专门针对复杂文档理解场景设计。它不仅能识别常规文本,还支持表格识别、公式识别等高级…...
颠覆式数据主权革命:WeChatMsg如何让你的聊天记录真正归属自己
颠覆式数据主权革命:WeChatMsg如何让你的聊天记录真正归属自己 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/…...
OpenClaw自动化测试:nanobot驱动浏览器执行回归用例
OpenClaw自动化测试:nanobot驱动浏览器执行回归用例 1. 为什么选择OpenClaw进行自动化测试 去年接手一个老项目时,我遇到了一个典型的前端测试困境——每次发版前需要手动执行87个回归测试用例,整个过程耗时近4小时。尝试过Selenium和Playw…...
30/50/20分期怎么设?SAP付款条件Z028实战案例详解(附基准日期避坑指南)
SAP非等额分期付款实战指南:30/50/20比例配置与基准日期避坑 在工程项目、大额设备采购等业务场景中,分期付款是常见的交易方式。不同于标准的等额分期,工程类合同常采用30/50/20这类非对称比例,首期支付30%预付款,中期…...
MCU高级开发技巧:外设驱动与系统架构优化
MCU高级用法解析:从外设驱动到系统架构设计1. MCU开发中的标准化与创新在嵌入式系统开发领域,MCU(微控制器单元)作为核心控制器件,其开发过程需要遵循严格的工程规范。标准的开发流程包括对变量和函数的明确定义,确定其生命周期、…...
OpenClaw+GLM-4.7-Flash:个人健康数据自动追踪与分析
OpenClawGLM-4.7-Flash:个人健康数据自动追踪与分析 1. 为什么需要自动化健康管理 去年体检报告上的几项异常指标让我意识到,碎片化的健康数据记录根本不足以反映真实身体状况。尝试过各种健康类App后,发现它们要么数据封闭,要么…...
告别兼容性烦恼:在Windows 11上为特定网站配置专属IE访问环境的完整指南
告别兼容性烦恼:在Windows 11上为特定网站配置专属IE访问环境的完整指南 当Windows 11彻底移除了IE浏览器的桌面入口,许多依赖特定网站的企业用户、财务人员和政府工作人员陷入了困境。那些仅兼容IE的老旧系统——从企业内部OA到税务申报平台,…...
