实验目的
- (1)理解内存管理中缺页的概念。
- (2)综合运用实验1,实验5,实验6中/proc文件系统、内存管理、系统调用、 内核编译的知识。
- (3)掌握向/proc文件系统中增加文件的方法。
- (4)掌握Linux内核模块的概念和操作方法。
实验内容
通过在内核中自建变量并利用/proc文件系统作为中介的方法来统计系统缺页次数:
- (1)在内核中实现缺页次数统计。
- (2)编译并安装新内核。
- (3)新建内核模块,并加载到新内核,通过/proc实现用户态下查看缺页次数。
实验环境
系统版本:Ubuntu 14.04 LTS
内核版本: Linux 3.2.0.29-generic
欲编译内核:Linux-2.6.32.60
实验步骤
第一部分:在内核中实现缺页次数统计
ubuntu@oslinux-virtual-machine:~$
cd /usr/src/linux-2.6.32.60
//切换到预编译内核目录
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo gedit arch/x86/mm/fault.c
//在do_page_fault函数上一行定义统计缺页次数全局变量pfcount
unsigned long volatile pfcount;
//将pfcount加入到do_page_fault中,用以统计缺页次数.
pfcount++;
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo gedit include/linux/mm.h
//声明全局变量pfcount到头文件mm.h中,在extern int page_cluster下面
添加代码:
extern unsigned long volatile pfcount;
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo gedit kernel/kallsyms.c
//导出pfcount全局变量,让整个内核都可以访问
//最后一行添加代码如下:
EXPORT_SYMBOL(pfcount);
第二部分:编译安装新内核
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo make mrproper
//删除原来编译产生的垃圾
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo cp /boot/config-3.2.0-29-generic-pae .config
//导入原系统的内核配置ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo make oldconfig
//更改配置,一直回车
//导入配置到欲编译内核中 )
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo make cleanubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo make bzImage
//编译内核
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo make modules
//编译模块
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo make modules_install
//添加模块到内核
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo make install
//链接、组建内核
ubuntu@oslinux-virtual-machine:~$ /usr/src/linux-2.6.32.60$
sudo reboot
//重新启动Linux系统重新启动Linux系统,开机时长按shift键直到进入启动加载界面,选择新编译的内核版本,按回车进入系统。进入系统后,使用命令uname –a 验证内核版本
是否安装成功
第三部分:新建内核模块,通过/proc实现用户态下查看缺页次数
ubuntu@oslinux-virtual-machine:~$ mkdir source
//系统重启后,创建source文件夹,用于存放编写的模块程序
ubuntu@oslinux-virtual-machine:~$ cd source/
//切换到source目录
ubuntu@oslinux-virtual-machine:~/source$ gedit pf.c
//新建用于构建模块的代码
ubuntu@oslinux-virtual-machine:~/source$
gedit Makefile
//构建Makefile,在Makefile中添加如下内容:
obj-m := pf.o
ubuntu@oslinux-virtual-machine:~/source$
sudo make -C /usr/src/linux-2.6.32.60 SUBDIRS=$PWD modules
//编译、构建内核模块
ubuntu@oslinux-virtual-machine:~/source$
sudo insmod pf.ko
//加载内核模块到内核中ubuntu@oslinux-virtual-machine:~/source$ sudo lsmod | grep pf
//验证pf内核模块是否加载到内核进程中,运行命令出现pf信息说明加载成功
ubuntu@oslinux-virtual-machine:~/source$ cat /proc/pf/pfcount
//打印/proc/pf/pfcount,查看缺页统计次数
实验结果
验证内核版本是否安装成功
验证pf内核模块是否加载到内核进程中,运行命令出现pf信息说明加载成功
打印/proc/pf/pfcount,查看缺页统计次数
核心代码
/*pf.c*/
/*内核模块代码*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <asm/uaccess.h>
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");
MODULE_AUTHOR("Aron.t.wang");