【linux系列】统计Linux系统缺页的次数

编译环境

  • 虚拟机操作系统: ubuntu-20.04.3-desktop-amd64
  • 原系统内核版本:5.11.0-46-generic
  • 内核源码版本:5.11.1

修改任务

  • 通过在Linux内核中自建变量,并利用 /proc 文件系统作为中介的方法,统计一段时间内系统缺页的次数。
  • 在内核中实现缺页次数统计。
  • 新建内核模块,编译并安装新内核。
  • 使用定时器设置开始和结束时间,通过 /proc 在用户态下查看该时间段内的缺页次数。

修改准备

修改源码

  • 需要修改的文件(默认从源码目录开始)如下:
arch/x86/mm/fault.c

include/linux/mm.h

kernel/kallsyms.c

修改 arch/x86/mm/fault.c
  • 定义 pfcount 变量

  • 搜索 trace_page_fault,并插入如下代码:

    unsigned long volatile pfcount;
    

    效果如下:
    在这里插入图片描述

  • 搜索 good_area:,并添加如下代码

    pfcount++;
    

    效果如下:
    在这里插入图片描述

修改 include/linux/mm.h
  • extern int page_cluster; 语句之后,添加如下代码:

    extern unsigned long volatile pfcount;
    

    效果如下:
    在这里插入图片描述

修改 kernel/kallsyms.c
  • 在最后一行添加如下代码:

    EXPORT_SYMBOL(pfcount);
    

    效果如下:
    在这里插入图片描述

编译安装

编写模块

  • 这里提供一份完整源码(readpfcount.c):
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <stdarg.h>

extern unsigned long volatile pfcount;
static struct timer_list test_timer;
static unsigned long pfcount_last;
static unsigned long pfcount_in_2;
static int count = 0;

MODULE_LICENSE("GPL");


/*5,实现show函数
  作用是将内核数据输出到用户空间
  将在proc file输出时被调用
  */
static int my_proc_show(struct seq_file *m, void *v)
{
    /*这里不能使用printfk之类的函数
      要使用seq_file输出的一组特殊函数
      */
	seq_printf(m, "[latest] Number of page fault interrupts in 2 seconds: %ld !\n", pfcount_in_2);
    return 0;
}

//定时器的回调函数
static void irq_test_timer_function(struct timer_list  *timer)
{
	
	printk("%d Number of page fault interrupts in 2 seconds: %ld\n",count,pfcount - pfcount_last);
	pfcount_in_2 = pfcount - pfcount_last;
	
	pfcount_last = pfcount;
	mod_timer(&test_timer, jiffies + 2 * HZ);
	count++;
}
 
static int my_proc_open(struct inode *inode, struct file *file)
{		
    /*4,在open函数中调用single_open绑定seq_show函数指针*/
    return single_open(file, my_proc_show, NULL);
}
 
/*2,填充proc_create函数中调用的flie_operations结构体
  其中my开头的函数为自己实现的函数,
  seq和single开头为内核实现好的函数,直接填充上就行
  open为必须填充函数
  */
static struct proc_ops my_fops = {
  .proc_open = my_proc_open,
  .proc_read = seq_read,
  .proc_lseek = seq_lseek,
  .proc_release = single_release,
};
 
static int __init my_init(void)
{


    struct proc_dir_entry *file;
    //创建父级目录,第二个参数NULL表示在/proc下
    //这里用我的学号当做文件名
    struct proc_dir_entry *parent = proc_mkdir("3190608027",NULL);

    /*1,
      首先要调用创建proc文件的函数,需要绑定flie_operations
      参数1:要创建的文件
      参数2:权限设置
      参数3:父级目录,如果传NULL,则在/proc下
      参数4:绑定flie_operations
      */
    file = proc_create("readpfcount", 0644, parent, &my_fops);
    if(!file)
        return -ENOMEM;
     
    //创建定时器  
    pfcount_last = pfcount;
	test_timer.expires  = jiffies + 2 * HZ;
	timer_setup(&test_timer, irq_test_timer_function, 0);
	
	add_timer(&test_timer);
	
	printk(KERN_INFO "already init and add timer\n");
    return 0;
}
 
/*6,删除proc文件*/
static void __exit my_exit(void)
{
  printk(KERN_INFO "exit timer drv\n");
  del_timer(&test_timer);
  //移除目录及文件
  remove_proc_entry("readpfcount", NULL);
}
 
module_init(my_init);
module_exit(my_exit);
  • 对应的 Makefile 文件:
ifneq ($(KERNELRELEASE),)
	obj-m:=readpfcount.o
else
	KDIR:= /usr/src/linux-5.11.1/
	PWD:= $(shell pwd)

default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean
endif

编译安装模块

  • 根据对应的 Makefile 文件,可以直接使用 sudo make 进行编译
  • 编译成功后会在当前文件夹下生成 .ko 文件
  • 使用 insmod 安装模块
  • 可以通过 dmesg 查看内核打印的信息
  • 可以通过 cat /proc/readpfcount 命令,通过 /proc 在用户态下查看该时间段内的缺页次数。
  • 效果如下图所示:
    在这里插入图片描述
  • 3
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鞠杉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值