简单记录一下 centos 自定义内核模块的一些编译运行记录,代码如下:
主要功能是通过rdtsc 指令直接从 CPU MSR 寄存器中获取时钟,尝试获取两次,两次之间会做一些赋值操作什么的,并记录一下时差。
#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/preempt.h>
#include <linux/sched.h>
void inline measured_function(volatile int *var) { (*var) = 1; }
static int __init hello_start(void) {
unsigned long flags;
uint64_t start, end;
int variable = 0;
unsigned cycles_low, cycles_high, cycles_low1, cycles_high1;
printk(KERN_INFO "Loading test module...\n");
preempt_disable(); /*we disable preemption on our CPU*/
raw_local_irq_save(flags); /*we disable hard interrupts on our CPU*/
/*at this stage we exclusively own the CPU*/
asm volatile(
"RDTSC\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t"
: "=r"(cycles_high), "=r"(cycles_low));
measured_function(&variable);
asm volatile(
"RDTSC\n\t"
"mov %%edx, %0\n\t"
"mov %%eax, %1\n\t"
: "=r"(cycles_high1), "=r"(cycles_low1));
raw_local_irq_restore(flags);
/*we enable hard interrupts on our CPU*/
preempt_enable(); /*we enable preemption*/
start = (((uint64_t)cycles_high << 32) | cycles_low);
end = (((uint64_t)cycles_high1 << 32) | cycles_low1);
printk(KERN_INFO "\n function execution time is %llu clock cycles",
(end - start));
return 0;
}
static void __exit hello_end(void) { printk(KERN_INFO "Goodbye Mr.\n"); }
module_init(hello_start);
module_exit(hello_end);
编译方式,Makefile
# obj-m 必须存在,后面的 .o 文件可以是自己的文件名,其他无需更改
obj-m := rdtsc_mode.o
KERNELBUILD :=/lib/modules/$(shell uname -r)/build
default:
make -C $(KERNELBUILD) M=$(shell pwd) modules
clean:
rm -rf *.o *.ko *.mod.c .*.cmd
将源代码文件和 makefile 放在一个目录之下,
sudo make
执行即可,执行成功之后会在当前目录下生成一个 rdtsc_mode.ko 文件。
[Fri Jan 14 16:41:52 2022] Loading test module...
[Fri Jan 14 16:41:52 2022] function execution time is 3504353503 clock cycles
[Fri Jan 14 16:42:11 2022] Goodbye Mr.