操作系统-统计操作系统缺页次数

统计操作系统缺页次数
1.实验目的
学习虚拟内存的基本原理和Linux虚拟内存管理技术;
深入理解、掌握Linux的按需调页过程;
掌握内核模块的概念和操作方法,和向/proc文件系统中增加文件的方法;
综合运用内存管理、系统调用、proc文件系统、内核编译的知识。
2.实验内容
1.原理
Linux的虚拟内存技术采用按需调页,当CPU请求一个不在内存中的页面时,会发生缺页,缺页被定义为一种异常(缺页异常),会触发缺页中断处理流程。每种CPU结构都提供一个do_page_fault处理缺页中断。由于每发生一次缺页都要进入缺页中断服务函数do_page_fault一次,所以可以认为执行该函数的次数就是系统发生缺页的次数。因此可以定义一个全局变量pfcount 作为计数变量,在执行do_page_fault时,该变量值加1。本实验通过动态加载模块的方法,利用/proc文件系统作为中介来获取该值。
2.实验环境
操作系统:Ubuntu 12.04(内核版本为3.2.0-23-generic-pae)
内核源码:linux-3.2.58
3.实验指导

  1. 下载一份内核源代码并解压
    Linux受GNU通用公共许可证(GPL)保护,其内核源代码是完全开放的。现在很多Linux的网站都提供内核代码的下载。推荐使用Linux的官方网站:http://www.kernel.org。

图1 Linux的官方网站
在terminal下可以通过wget命令下载源代码:
$ cd /tmp
$ wget http://www.kernel.org/pub/linux/kernel/v3.x/linux-3.2.58.tar.xz
切换到root身份,解压源代码到/usr/src目录下:

sudo apt-get install xz-utils
 xz –d linux-3.2.58.tar.xz
 tar –xvf linux-3.2.58.tar –C /usr/src

失败的话,

tar xvJf  filename -C 指定目录

直接解压到指定文件目录
报错的话,就别移动了,解压到当前目录在移动吧

tar xvJf  filename
mv 文件夹名1 文件夹名2 (文件夹1存在)
  1. 修改内核源代码,添加统计变量
    1、切换到预编译内核目录
    #cd /usr/src/linux-3.2.58
    2、修改处理内存访问异常的代码
    //用vi编辑器打开fault.c,一般使用Intel x86体系结构,则修改arch/x86/目录下的文件
    #vi arch/x86/mm/fault.c
    //在do_page_fault函数的上一行定义统计缺页次数的全局变量pfcount
    unsigned long volatile pfcount;
    //将pfcount加入到do_page_fault中,用以统计缺页次数
    pfcount++;
    操作系统-统计操作系统缺页次数_第1张图片

3、修改内存管理代码
//用vi编辑器打开头文件mm.h
#vi include/linux/mm.h
//在mm.h中加入全局变量pfcount的声明,代码加在extern int page_cluster;语句之后
extern unsigned long volatile pfcount;
操作系统-统计操作系统缺页次数_第2张图片

4、导出pfcount全局变量,让整个内核(包括模块)都可以访问。方法是:
#vi kernel/kallsyms.c
Shift+g 跳到文章最后
//在文件最后加入一行代码
EXPORT_SYMBOL(pfcount);
操作系统-统计操作系统缺页次数_第3张图片

  1. 配置编译新内核
    用编译Linux内核预备实验中的方法完成新内核的配置、编译、替换,重启后验证是否完成替换。
    #uname –r //如果为3.2.58(与你采用的新内核版本一至)说明替换完成
    在这里插入图片描述

操作系统-统计操作系统缺页次数_第4张图片

1.make mrproper,删除原来编译产生的垃圾,如果是第一次编译的话可以不用
2.cp /boot/config-4.4.0-148-generic .config
复制自己当前内核的配置文件,可以用uname -r 查看内核版本然后对应自己/boot下面的文件
3.make menuconfig会弹出一个像图形界面的东西,左右横移选择save之后exit就好
报错就执行
apt install libncurses5-dev
4.make -j4 all
5. make modules编译模块
6.make modules_install添加模块到内核
7.make install组建内核 然后reboot重启
8.这里可能你启动的时候没有让你选择的界面gedit  /etc/default/grub 修改一下配置 

Ok 现在启动选择内核,然后在终端输入uname -r 

操作系统-统计操作系统缺页次数_第5张图片在这里插入图片描述

  1. 编写读取pfcount值的模块代码
    系统重启后,执行如下操作:
    #mkdir source //在当前用户目录下创建source文件夹,用于存放编写的用户程序
    #cd source //切换到source目录
    #vi pf.c //新建用于构建模块的代码

/pf.c/

/*modules program*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct proc_dir_entry *proc_pf;     
struct proc_dir_entry *proc_pfcount;
extern unsigned long volatile pfcount;

static inline struct proc_dir_entry *proc_pf_create(const char* name, mode_t mode, read_proc_t * get_info)
{
    return create_proc_read_entry(name,mode,proc_pf,get_info,NULL);
}

int get_pfcount(char *buffer, char **start, off_t offset, int length, int *peof, void *data)
{
    int len = 0;
    len = sprintf(buffer, "%ld \n", pfcount);
    return len;
}

static int pf_init(void)
{
    proc_pf = proc_mkdir("pf", 0);
    proc_pf_create("pfcount", 0, get_pfcount);
    return 0;
}

static void pf_exit(void)
{
    remove_proc_entry("pfcount",proc_pf);
    remove_proc_entry("pf",0);
}

module_init(pf_init);
module_exit(pf_exit);
MODULE_LICENSE("GPL");
  1. 编译、构建内核模块
    #vi Makefile //在source目录下建立Makefile文件
    在Makefile中添加如下内容:
ifneq ($(KERNELRELEASE),)
	obj-m:=pf.o
else
	KDIR:= /lib/modules/$(shell uname -r)/build
	PWD:= $(shell pwd)
default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean
Endif

操作系统-统计操作系统缺页次数_第6张图片

  1. 加载模块到内核中
    执行加载模块命令:
    #insmod pf.ko
    查看统计缺页次数:
    #cat /proc/pf/pfcount
    操作系统-统计操作系统缺页次数_第7张图片
    在这里插入图片描述

4.实验心得
通过本次实验,用了一下午终于搞完了,用了两次机会才成功,第一次不会搞,就瞎搞结果导致出现一堆不知名的文件,最后删除干净。再第二次实验用了很短时间就搞定了,在修改文件的时候一定要小心,不然,编译的时候报错,真的很烦。说实话,我没学到多少东西,是真的,我也不明白,可能光顾着跟着教程一步一步写,没有思考吧,说真的,真是看不懂,实在要说收获的话,我只能说我会更换Ubuntu的内核,还会统计缺页次数,也知道,操作系统真的太复杂了,学习的路很长,长的让我发慌。

你可能感兴趣的:(学习笔记,linux,服务器,操作系统)