实验3 统计操作系统缺页次数
实验目的
学习操作系统的存储管理原理;理解操作系统存储管理的分页、虚拟内存、“按需调页”思想及方法;掌握Linux 内核对虚拟内存、虚存段、分页式存储管理、按需调页的实现机制。 实验内容
进行实验前,务必先行阅读、理解Linux 内核的关于存储管理的源代码,理解Linux 存储管理的整体思想。因为,本实验比较简单,没能覆盖Linux 内核中存储管理的所有内容。 实验共做两个。第一个实验统计自内核加载完成以后到当前时刻为止发生的缺页次数和经历过的时间;第二个实验统计从当前时刻起一段时间内发生的缺页中断次数。两者的实现方法略有不同。
实验指导
3.1系统缺页次数
看看这个实验怎么通过自建变量并利用/proc文件系统,来统计自系统启动以来,系统的缺页次数。
3.1.1 实验原理
由于每发生一次缺页都要进入缺页中断服务函数do_page_fault一次,所以可以认为执行该函数的次数就是系统发生缺页的次数。因此可以定义一个全局变量pfcount 作为计数变量,在执行do_page_fault时,该变量值加1。
至于系统自开机以来经历的时间,可以利用系统原有的变量jiffies 。这是一个系统的计时器,在内核加载完以后开始计时,以10ms (缺省)为计时单位。
当然,读取变量pfcount 和变量jiffies 的值,还需要借助/proc文件系统。在/proc文件系统下建立目录pf ;并且在pf 目录下,建立文件pfcount 和jiffies 。
3.1.2 实验实施
先在include/linux/mm.h文件中声明变量pfcount :
--- linux-2.6.15/include/linux/mm.h.orig
+++ linux-2.6.15/include/linux/mm.h
***************
*****26,29*****
extern unsigned long num_physpages;
extern void * high_memory;
extern unsigned long vmalloc_earlyreserve;
extern int page_cluster;
+ extern unsigned long pfcount;
在arch/i386/mm/fault.c文件中定义变量pfcount :
--- linux-2.6.15/arch/i386/mm/fault.c.orig
+++ linux-2.6.15/arch/i386/mm/fault.c
***************
****227,235****
+ unsigned long pfcount;
fastcall void __kprobes do_page_fault(struct pt_regs *regs,
{
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct * vma;
unsigned long address;
unsigned long page;
int write, si_code; unsigned long error_code)
每次产生缺页中断,并且确认是由缺页引起的,则将变量值递增1。这个操作在do_page_fault()函数中执行:
--- linux-2.6.15/arch/i386/mm/fault.c.orig
+++ linux-2.6.15/arch/i386/mm/fault.c
***************
****328,328****
goodarea:
+ pfcount++;
在/kernel/time.c文件中加入EXPORT_SYMBOL(pfcount),让内核模块能够读取变量pfcount ;同理,内核模块也可以读取jiffies :
--- linux-2.6.15/kernel/time.c.orig
+++ linux-2.6.15/kernel/time.c
***************
****687,687****
EXPORT_SYMBOL(jiffies);
+ extern unsigned long pfcount;
+ EXPORT_SYMBOL(pfcount);
以上部分是对Linux 内核源代码的几处修改。若让它们起作用,显然,需要重新编译内核,产生新的内核的image ;并且,重新启动主机,装入新编译生成的image 。内核的编译和装入,可参见“编译Linux 内核”一章。
读取pfcount 和jiffies 变量的内核模块,需要新编写一个文件:pf . c
#define MODULE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct proc_dir_entry *proc_pf; /*/proc/pf/ 目录项*/
struct proc_dir_entry *proc_pfcount, *proc_jiffies; /* /proc/pf/pfcount和/proc/pf/jiffies 文件项*/
/*下面这个函数用于建立/proc/pf/ 目录项*/
static inline struct proc_dir_entry *proc_pf_create(const char* name, mode_t mode,
get_info_t *get_info)
{
return create_proc_info_entry(name, mode, proc_pf, get_info);
}
/*读取pfcount 的值*/
int get_pfcount(char *buffer, char **start, off_t offset, int length)
{
int len = 0;
len = sprintf(buffer, "%d\n", pfcount);
/* pfcount is defined in arch/i386/mm/fault.c */
return len;
}
/*读取 jiffies 的值*/
int get_jiffies(char *buffer, char **start, off_t offset, int length)
{
int len = 0;
len = sprintf(buffer, "%d\n", jiffies);
return len;
}
/*模块初始化进程,建立/proc下的目录和项*/
int init_module(void)
{
proc_pf = proc_mkdir("pf", 0);
proc_pf_create("pfcount", 0, get_pfcount);
proc_pf_create("jiffies", 0, get_jiffies);
return 0;
}
/*模块清除进程,清除/proc下的相关目录和文件*/
void cleanup_module(void)
{
remove_proc_entry("pfcount", proc_pf);
remove_proc_entry("jiffies", proc_pf);
remove_proc_entry("pf", 0);
}
MODULE_LICENSE(“GPL ”);
在编译内核模块前,先准备一个Makefile :
TARGET = pf
KDIR = /usr/src/linux
PWD = $(shell pwd)
obj-m += $(TARGET).o
default:
make -C $(KDIR) M=$(PWD) modules
然后简单输入命令make :
#make
结果,我们得到文件“pf.ko ”!这意味着,你成功了。
然后执行加载模块命令:
#insmod pf.ko
这样就可以通过作为中介的/proc文件系统,轻松地读取我们所需要的两个变量的值了。使用命令cat /proc/pf/pfcount /proc/pf/jiffies,就可以在终端打印出至今为止的缺页次数和已经经历过的jiffies 数目。
隔几分钟再使用命令cat /proc/pf/pfcount /proc/pf/jiffies,查看一下打印出的缺页次数和jiffies 数目。比较一下结果。
实验3 统计操作系统缺页次数
实验目的
学习操作系统的存储管理原理;理解操作系统存储管理的分页、虚拟内存、“按需调页”思想及方法;掌握Linux 内核对虚拟内存、虚存段、分页式存储管理、按需调页的实现机制。 实验内容
进行实验前,务必先行阅读、理解Linux 内核的关于存储管理的源代码,理解Linux 存储管理的整体思想。因为,本实验比较简单,没能覆盖Linux 内核中存储管理的所有内容。 实验共做两个。第一个实验统计自内核加载完成以后到当前时刻为止发生的缺页次数和经历过的时间;第二个实验统计从当前时刻起一段时间内发生的缺页中断次数。两者的实现方法略有不同。
实验指导
3.1系统缺页次数
看看这个实验怎么通过自建变量并利用/proc文件系统,来统计自系统启动以来,系统的缺页次数。
3.1.1 实验原理
由于每发生一次缺页都要进入缺页中断服务函数do_page_fault一次,所以可以认为执行该函数的次数就是系统发生缺页的次数。因此可以定义一个全局变量pfcount 作为计数变量,在执行do_page_fault时,该变量值加1。
至于系统自开机以来经历的时间,可以利用系统原有的变量jiffies 。这是一个系统的计时器,在内核加载完以后开始计时,以10ms (缺省)为计时单位。
当然,读取变量pfcount 和变量jiffies 的值,还需要借助/proc文件系统。在/proc文件系统下建立目录pf ;并且在pf 目录下,建立文件pfcount 和jiffies 。
3.1.2 实验实施
先在include/linux/mm.h文件中声明变量pfcount :
--- linux-2.6.15/include/linux/mm.h.orig
+++ linux-2.6.15/include/linux/mm.h
***************
*****26,29*****
extern unsigned long num_physpages;
extern void * high_memory;
extern unsigned long vmalloc_earlyreserve;
extern int page_cluster;
+ extern unsigned long pfcount;
在arch/i386/mm/fault.c文件中定义变量pfcount :
--- linux-2.6.15/arch/i386/mm/fault.c.orig
+++ linux-2.6.15/arch/i386/mm/fault.c
***************
****227,235****
+ unsigned long pfcount;
fastcall void __kprobes do_page_fault(struct pt_regs *regs,
{
struct task_struct *tsk;
struct mm_struct *mm;
struct vm_area_struct * vma;
unsigned long address;
unsigned long page;
int write, si_code; unsigned long error_code)
每次产生缺页中断,并且确认是由缺页引起的,则将变量值递增1。这个操作在do_page_fault()函数中执行:
--- linux-2.6.15/arch/i386/mm/fault.c.orig
+++ linux-2.6.15/arch/i386/mm/fault.c
***************
****328,328****
goodarea:
+ pfcount++;
在/kernel/time.c文件中加入EXPORT_SYMBOL(pfcount),让内核模块能够读取变量pfcount ;同理,内核模块也可以读取jiffies :
--- linux-2.6.15/kernel/time.c.orig
+++ linux-2.6.15/kernel/time.c
***************
****687,687****
EXPORT_SYMBOL(jiffies);
+ extern unsigned long pfcount;
+ EXPORT_SYMBOL(pfcount);
以上部分是对Linux 内核源代码的几处修改。若让它们起作用,显然,需要重新编译内核,产生新的内核的image ;并且,重新启动主机,装入新编译生成的image 。内核的编译和装入,可参见“编译Linux 内核”一章。
读取pfcount 和jiffies 变量的内核模块,需要新编写一个文件:pf . c
#define MODULE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct proc_dir_entry *proc_pf; /*/proc/pf/ 目录项*/
struct proc_dir_entry *proc_pfcount, *proc_jiffies; /* /proc/pf/pfcount和/proc/pf/jiffies 文件项*/
/*下面这个函数用于建立/proc/pf/ 目录项*/
static inline struct proc_dir_entry *proc_pf_create(const char* name, mode_t mode,
get_info_t *get_info)
{
return create_proc_info_entry(name, mode, proc_pf, get_info);
}
/*读取pfcount 的值*/
int get_pfcount(char *buffer, char **start, off_t offset, int length)
{
int len = 0;
len = sprintf(buffer, "%d\n", pfcount);
/* pfcount is defined in arch/i386/mm/fault.c */
return len;
}
/*读取 jiffies 的值*/
int get_jiffies(char *buffer, char **start, off_t offset, int length)
{
int len = 0;
len = sprintf(buffer, "%d\n", jiffies);
return len;
}
/*模块初始化进程,建立/proc下的目录和项*/
int init_module(void)
{
proc_pf = proc_mkdir("pf", 0);
proc_pf_create("pfcount", 0, get_pfcount);
proc_pf_create("jiffies", 0, get_jiffies);
return 0;
}
/*模块清除进程,清除/proc下的相关目录和文件*/
void cleanup_module(void)
{
remove_proc_entry("pfcount", proc_pf);
remove_proc_entry("jiffies", proc_pf);
remove_proc_entry("pf", 0);
}
MODULE_LICENSE(“GPL ”);
在编译内核模块前,先准备一个Makefile :
TARGET = pf
KDIR = /usr/src/linux
PWD = $(shell pwd)
obj-m += $(TARGET).o
default:
make -C $(KDIR) M=$(PWD) modules
然后简单输入命令make :
#make
结果,我们得到文件“pf.ko ”!这意味着,你成功了。
然后执行加载模块命令:
#insmod pf.ko
这样就可以通过作为中介的/proc文件系统,轻松地读取我们所需要的两个变量的值了。使用命令cat /proc/pf/pfcount /proc/pf/jiffies,就可以在终端打印出至今为止的缺页次数和已经经历过的jiffies 数目。
隔几分钟再使用命令cat /proc/pf/pfcount /proc/pf/jiffies,查看一下打印出的缺页次数和jiffies 数目。比较一下结果。