文档库 最新最全的文档下载
当前位置:文档库 › 华南理工大学《操作系统》大作业报告

华南理工大学《操作系统》大作业报告

华南理工大学《操作系统》大作业报告

题目:高级操作系统与分布式系统大作业

学院计算机科学与工程

专业计算机科学与技术(全英创新班)

学生姓名 xxxxxx

学生学号 2012********

联系方式 _156********(Tel)/651476895(QQ)_

指导教师吴一民

课程编号S0812011

课程学分2 分

起始日期 2016年1月11日

实验过程:

内核安装

1.安装vmware workstation,并在其上安装CentOS5.8。

2.安装vmware-tools,设置共享文件夹。并把内核文件linux-2.6.18.tar.xz下载至共享文

件夹当中(/mnt/hgfs/sharedFiles)。

3.登录root,把内核文件压缩包解压至/usr/src目录下:

# tar -xvf linux-3.13.2.tar.xz -C /usr/src/

4.安装gcc和ncurses包:

yum -y install gcc

yum install ncurses ncurses-deve

5.进行内核配置:

make menuconfig

6.进入usr/src/linux-2.6.18/目录编译内核:

cd usr/src/linux-2.6.18/

make

make modules_install

7.安装内核:

make install

8.内核版本验证:

vim /boot/grub/grub.conf查看内核版本列表,可以看到2.6.18内核已安装,修改default=0,默认启动新安装的内核。

9.重启,查看内核版本:

uname–a内核从2.6.18-308变为2.6.18,内核安装成功。

记录系统调用次数

1.创建一个全局数组记录系统调用次数

在/usr/src/linux-2.6.18/kernel/sys.c中添加一个callCount数组记录系统调用次数

vim /usr/src/linux-2.6.18/kernel/sys.c

long callCount [NR_syscalls];

EXPORT_SYMBOL (callCount);

其中NR_syacalls是sys.c中的一个宏,记录了系统调用的数量。

2.修改system_call(),使其能对每个系统调用进行计数

在/usr/src/linux-2.6.18/arch/i386/kernel/entry.S的syscall_call:和call *sys_call_table(,%eax,4)之间插入语句:

vim /usr/src/linux-2.6.18/arch/i386/kernel/entry.S

incl callCount(,%eax,4)

incl callCount(,%eax,4)这条会变代码的含义是:incl是对后面的地址的内容进行自增操作,也就是对callCount(,%eax,4)这个元素的内容+1。其中eax是用户空间传递到eax寄存器中的系统调用号。,%eax,4的含义是eax寄存器里面的值乘以4,由于系统调用表中的表项是以32位(4字节)类型存放的,所以内核需要将给定的系统调用号乘以4,所以是对callCount第%eax*4个元素进行增量操作。

3.在系统调用表中增加表项

在/usr/src/linux-2.6.18/arch/i386/kernel/syscall_table.S尾部添加三个系统调用的表项:.long sys_allSysCall

.long sys_spcSysCall

.long sys_clrSysCall

翻到syscall_table.S的头部可以看到下图内容,这个文件存储的是系统调用表,实际上就是sys_call_table这个数组,共有NR_syscalls个表项。语句前面的点号’’.’指的是当前的地址,sys_call_table是数组的首地址,调用表中的第321个表项sys_clrSysCall指代系统调用号为320的clcSysCall()服务例程地址。这个表项的作用就是用来通过系统调用号索引内核服务例程。

4.为三个新增的系统调用添加系统调用号的宏

在/usr/src/linux-2.6.18/include/asm/unistd.h中添加三个系统调用的调用号:

#define __NR_allSysCall 318

#define __NR_spcSysCall 319

#define __NR_clrSysCall 320

把__NR_syscalls这个记录系统调用总数的宏增加3

#define __NR_syscalls 321

5.在头文件中声明三个系统调用

在/usr/src/linux-2.6.18/include/linux/syscalls.h的尾部添加:

asmlinkage int sys_allSysCall(void);

asmlinkage int sys_spcSysCall(int sys_callNum);

asmlinkage int sys_clrSysCall(void);

syscall.h这个头文件适用于实现系统调用表中指向的服务例程,在本实验中,我定义了三个函数:

(1)allSysCall:接受0个参数,用于显示所有系统调用被执行的次数。

(2)spcSysCall: 接受1个参数,查询的系统调用号作为参数,用于显示某个特定

的系统调用被执行的次数,返回值为该系统调用被调用的次数。参数不合法

时返回-1。

(3)clrSysCall:接受0个参数,用于把系统调用次数数组清零。

6.为三个系统调用增加具体实现

在/usr/src/linux-2.6.18/kernel/sys.c中实现这三个函数:

asmlinkage int sys_allSysCall(void){

int i=0;

printk("Times of system calls\n");

for(;i

printk("System call [%d] was called %ld times. \n",i,callCount[i]);

return 0;}

asmlinkage int sys_spcSysCall(int callNum){

if(callNum< NR_syscalls && callNum >= 0){

printk("System call --%d has been call %ld time(s). \n",callNum,mycount[callNum]);

return callCount[callNum];}

else{

printk("Inviliad system call number.\n");

return -1;}}

asmlinkage int sys_clrSysCall(void){

int i=0;

for (;i < NR_syscalls;i++)

callCount[i]=0;

printk("Times of system call setted to 0.\n");

return 0;}

7.重新编译内核

8.编写测试函数

(1)测试allSysCall():

test_allSysCall.c

#include

#include

#include

#include

#define test_allSysCall 318

int main()

{

syscall(test_allSysCall);

return 0;

}

测试结果:

所有系统调用的次数都已被列出(这里只显示前几个),函数正常工作。

(2)测试spcSysCall():

test_spcSysCall.c

#include

#include

#include

#include

#define test_spcSysCall 319

int main()

{

int sysNum;

scanf("%d",&sysNum);

syscall(test_spcSysCall,sysNum);

return 0;

}

测试结果:

第200个系统调用被调用3685次,函数正常工作。

(3)测试spcSysCall():

test_clrSysCall.c

#include

#include

#include

#include

#define test_allSysCall 318

#define test_clrSysCall 320

int main()

{

syscall(test_clrSysCall);

syscall(test_allSysCall);

return 0;

}

测试结果:

所有系统调用执行次数都被清零,除了部分函数立即得到执行,计数为1,函

数正常工作。

如何验证我的代码

1.进入虚拟机,通过账号root,密码aaasss登录,进入目录/home/testSC

cd /home/testSC

2.验证allSysCall()函数(列出所有系统调用执行次数),执行如下命令:

gcc -o result_allSysCall test_allSysCall.c

(执行test_allSysCall.c代码,生成可执行文件result_allSysCall)

./result_allSysCall

(运行代码查看执行结果,在这里能看到所有系统调用执行次数)

3.验证clrSysCall()函数(清零所有系统调用执行次数),执行如下命令:

gcc–o result_clrSysCall test_clrSysCall.c

(执行test_clrSysCall.c代码,生成可执行文件result_clrSysCal中)

./result_clrSysCall

(运行代码查看执行结果,这里能清零所有系统调用执行次数,并查看清零结果)

实验过程:

缺页查询、清零

1.在进程的task_struct中新增一个计数变量,用于记录进程发生缺页的次数

在/usr/src/linux-2.6.18/include/linux/sched.h中添加一个faultTimes成员

vim /usr/src/linux-2.6.18/include/linux/sched.h

long faultTimes;

2.进程初始化时,为faultTimes清零

在/usr/src/linux-2.6.18/include/linux/init_task.h的进程初始化#define INIT_TASK(tsk)宏中使faultTimes清零:

vim /usr/src/linux-2.6.18/include/linux/init_task.h

.faultTimes =0, \

3.复制进程时,为faultTimes清零

在/usr/src/linux-2.6.18/kernel/fork.c的copy_process()函数为进程复制调用的函数,在该函数返回之前,为faultTimes清零:

vim /usr/src/linux-2.6.18/kernel/fork.c

p-> faultTimes = 0;

4.定义一个全局变量用来记录总的缺页次数,并为该变量加自旋锁

在/usr/src/linux-2.6.18/arch/i386/mm/fault.c中增加一个totalFault变量记录总的缺页次数。因为内核抢占等原因会造成异步执行,所以要对该变量加上自旋锁pageLock:vim /usr/src/linux-2.6.18/arch/i386/mm/fault.c

unsigned long totalFault=0;

spinlock_t pageLock=SPIN_LOCK_UNLOCKED;

unsigned long lockFlag;

EXPORT_SYMBOL(totalFault);

EXPORT_SYMBOL(pageLock);

EXPORT_SYMBOL(lockFlag);

5.实现缺页计数器自增操作

每次发生缺页时,会调用/usr/src/linux-2.6.18/arch/i386/mm/fault.c中的do_page_fault()函数,在该函数tsk = current之后完成自增操作,同时注意使用自旋锁保护变量:vim /usr/src/linux-2.6.18/arch/i386/mm/fault.c

spin_lock_irqsave(&pageLock,lockFlag);

totalFault++;

spin_unlock_irqrestore(&pageLock,lockFlag);

spin_lock_irqsave(&pageLock,lockFlag);

tsk->faultTimes++;

spin_unlock_irqrestore(&pageLock,lockFlag);

6.在系统调用表中增加表项

在/usr/src/linux-2.6.18/arch/i386/kernel/syscall_table.S尾部添加三个系统调用的表项:.long sys_allFault

.long sys_spcFault

.long sys_clrFault

翻到syscall_table.S的头部可以看到下图内容,这个文件存储的是系统调用表,实际上就是sys_call_table这个数组,共有NR_syscalls个表项。语句前面的点号’’.’指的是当前的地址,sys_call_table是数组的首地址,调用表中的第323个表项sys_clrFault() 指代系统调用号为322的clcFault ()服务例程地址。这个表项的作用就是用来通过系统调用号索引内核服务例程。

7.为三个新增的系统调用添加系统调用号的宏

在/usr/src/linux-2.6.18/include/asm/unistd.h中添加三个系统调用的调用号:

#define __NR_allFault 321

#define __NR_spcFault 322

#define __NR_clrFault 323

把__NR_syscalls这个记录系统调用总数的宏增加3

#define __NR_syscalls 324

8.在头文件中声明三个系统调用

在/usr/src/linux-2.6.18/include/linux/syscalls.h的尾部添加:

asmlinkage int sys_allFault(void);

asmlinkage int sys_spcFault(int pid);

asmlinkage int sys_clrFault(void);

syscall.h这个头文件适用于实现系统调用表中指向的服务例程,在本实验中,我定义了三个函数:

(1)allFault:接受0个参数,用于显示所有进程的缺页次数和总的缺页数。

(2)spcFault: 接受1个参数,查询的进程PID作为参数,用于显示某个特定的进

程缺页的次数,返回值为该进程缺页的次数。参数不合法时返回-1。

(3)clrFault:接受0个参数,用于把进程缺页计数和总缺页数清零。

9.在实现系统调用的c文件中引用缺页计数器和自旋锁的定义

在/usr/src/linux-2.6.18/kernel/sys.c中引用在fault.c中定义的totalFault,pageLock和lockFlag变量,否则不能访问这几个变量:

extern unsigned long totalFault;

extern spinlock_t pageLock;

extern unsigned long lockFlag;

10.为三个系统调用增加具体实现

在/usr/src/linux-2.6.18/kernel/sys.c中实现这三个函数:

v im /usr/src/linux-2.6.18/kernel/sys.c

asmlinkage int sys_allFault(void){

struct task_struct *pfTask;

printk("Total faults: [%ld] times\n",totalFault);

for_each_process(pfTask)

printk("Task %d : (%ld) times for page fault.\n",pfTask->pid,pfTask->faultTimes);

return 0;

}

asmlinkage int sys_spcFault(int pid){

struct task_struct *pfTask;

for_each_process(pfTask){

if(pfTask->pid==pid){

printk("Task %d : (%ld) times for page fault.\n",pfTask->pid,pfTask->faultTimes);

return pfTask->faultTimes;}

}

return -1;

}

asmlinkage int sys_clrFault(void){

struct task_struct *pfTask;

spin_lock_irqsave(&pageLock,lockFlag);

totalFault=0;

for_each_process(pfTask)

pfTask->faultTimes=0;

spin_unlock_irqrestore(&pageLock,lockFlag);

printk("Fault times cleared. \n");

return 0;}

11.重新编译内核

12.编写测试函数

(1)测试allFault():

test_allFault.c

#include

#include

#include

#include

#define sys_allFault 321

int main()

{

syscall(sys_allFault);

return 0;

}

测试结果:

所有进程的缺页次数、总的缺页次数都已被列出(这里只显示部分几个),函

数正常工作。

(2)测试spcFault():

test_spcFault.c

#include

#include

#include

#include

#define sys_spcFault 322

int main()

{

int tskNum;

scanf("%d",&tskNum);

syscall(sys_spcFault,tskNum);

return 0;}

测试结果:

PID为的进程缺页次,函数正常工作。

(3)测试clrFault():

test_clrSysCall.c

#include

#include

#include

#include

#define sys_allFault 321

#define sys_clrFault 323

int main()

{

printf("------Fault times before clear------\n");

syscall(sys_allFault);

printf("------Clearing fault times------\n");

syscall(sys_clrFault);

printf("------Fault times after clear------\n");

syscall(sys_allFault);

return 0;

}

测试结果:

总的缺页次数清零,进程的缺页清零,函数正常工作。

相关文档
相关文档 最新文档