华南理工大学《操作系统》大作业报告(共19页).docx
《华南理工大学《操作系统》大作业报告(共19页).docx》由会员分享,可在线阅读,更多相关《华南理工大学《操作系统》大作业报告(共19页).docx(20页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、精选优质文档-倾情为你奉上华南理工大学操作系统大作业报告题目:高级操作系统与分布式系统大作业学 院 计算机科学与工程 专 业 计算机科学与技术(全英创新班) 学生姓名 xxxxxx 学生学号 2012* 联系方式 _(Tel)/(QQ)_指导教师 吴一民 课程编号 S 课程学分 2 分 起始日期 2016年1月11日 实验概述【实验目的及要求】内核版本要求: Linux-2.6.18实验任务: 1.修改system_call(),使内核能够记录每一个系统调用被使用的次数。同时,为了使应用程序能够查询到这些数据,本实验要求实现两个系统调用,一个供应用程序来查询某个特定系统调用被使用的次数,另一个
2、系统调用将系统调用计数清零。编制一个用户态程序调用你所增加的这两个系统调用,统计在一段时间内各系统调用被调用的次数。2.修改系统的缺页异常处理程序使之能够记录系统缺页次数和当前进程的缺页次数。同样,本实验也要求实现两个系统调用,一个供应用程序查询缺页次数,另一个系统调用将缺页计数清零。编制一个用户态程序你所增加的这两个系统调用,统计在一段时间内你的进程缺页的次数。【实验环境】操作系统: Centos-5.8-i386(内核版本2.6.18-308)编译的内核: 2.6.18虚拟机: 12.1.0.2487【虚拟机账号密码】账号:root密码:aaasss实验一实验内容【实验原理】linux系统
3、调用是linux在其内核里都有一些内建的,这些函数可以用来完成一些系统级别的功能。这些代表了从到的一种转换,例如在用户空间调用open函数,则会在调用sys_open。Linux中每个系统调用都有相应的系统调用号,这样,通过这个独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就被用来指明到底是要执行哪个系统调用。进程不会提及系统调用的名称。在这次试验采用的linux-2.6.18内核中共有317个系统调用,他们储存在sys_call_table的数据结构当中,这个数据结构在此内核中的entry.S中定义。sys_call_table是一张由指向实现各种系统
4、调用的内核函数的函数指针组成的表。在用户空间无法直接调用系统调用来执行内核代码,所以需要通过软中断的方式来实现系统调用。通过int $0x80指令产生系统软中断,触发异常使得系统切换到内核态执行128号异常处理程序,调用system_call()函数。但是仅仅陷入内核空间是不够的,还需要通过eax寄存器把相应的系统调用号传递给内核。在陷人内核之前,用户空间就把相应系统调用所对应的号放入eax中了。这样系统调用处理程序一旦运行,就可以从eax中得到数据。system_call()函数通过将给定的系统调用号与NR_syscalls做比较来检查其有效性。如果它大于或者等于NR syscalls,该函
5、数就返回一ENOSYS。否则,就执行相应的系统调用。由于系统调用表中的表项是以32位(4字节)类型存放的,所以内核需要将给定的系统调用号乘以4,然后用所得的结果在该表中查询其位置。Linux系统本身并未有记录系统调用次数的数据结构,因此我们需要在内核中定义一个全局数组来记录每个系统调用被执行的次数。从调用的原理上看,要记录每个系统调用被执行的次数,我们可以在system_call()参数检查成功后,对相应的系统调用次数做一次增量操作,这样就完成了执行次数记录的工作。为了能得到该数组信息和对该数组进行操作,我们还需要定义自己的系统调用。我们定义的系统调用可以相应地在entry.S中的sys_ca
6、ll_table添加,并重新编译内核,使用该函数。实验过程:内核安装1. 安装vmware workstation,并在其上安装CentOS 5.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 gccyum install ncurses ncurses-
7、deve5. 进行内核配置:make menuconfig6. 进入usr/src/linux-2.6.18/目录编译内核:cd usr/src/linux-2.6.18/makemake modules_install7. 安装内核:make install8. 内核版本验证:vim /boot/grub/grub.conf 查看内核版本列表,可以看到2.6.18内核已安装,修改default=0,默认启动新安装的内核。9. 重启,查看内核版本:uname a 内核从2.6.18-308变为2.6.18,内核安装成功。记录系统调用次数1. 创建一个全局数组记录系统调用次数在/usr/src/
8、linux-2.6.18/kernel/sys.c中添加一个callCount数组记录系统调用次数vim /usr/src/linux-2.6.18/kernel/sys.clong 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
9、)之间插入语句: vim /usr/src/linux-2.6.18/arch/i386/kernel/entry.Sincl 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.
10、 在系统调用表中增加表项在/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指代系统调用号为32
11、0的clcSysCall()服务例程地址。这个表项的作用就是用来通过系统调用号索引内核服务例程。4. 为三个新增的系统调用添加系统调用号的宏在/usr/src/linux-2.6.18/include/asm/unistd.h中添加三个系统调用的调用号:#define _NR_allSysCall318#define _NR_spcSysCall 319#define _NR_clrSysCall 320把_NR_syscalls这个记录系统调用总数的宏增加3#define _NR_syscalls 3215. 在头文件中声明三个系统调用在/usr/src/linux-2.6.18/inclu
12、de/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个参数,查询的系统调用号作为参数,用于显示某个特定的系统调用被执行的次数,返回值为该系统调用被调用的
13、次数。参数不合法时返回-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 callsn);for(;iNR_syscalls;i+) printk(System call %d was called %ld times. n,i,callCounti);return 0; asmlinkage int sys_spcSy
14、sCall(int callNum)if(callNum = 0) printk(System call -%d has been call %ld time(s). n,callNum,mycountcallNum);return callCountcallNum; elseprintk(Inviliad system call number.n);return -1; asmlinkage int sys_clrSysCall(void)int i=0; for (;i NR_syscalls;i+) callCounti=0;printk(Times of system call set
15、ted to 0.n);return 0; 7. 重新编译内核8. 编写测试函数(1) 测试allSysCall():test_allSysCall.c #include#include#include#include#define test_allSysCall 318int main()syscall(test_allSysCall);return 0;测试结果:所有系统调用的次数都已被列出(这里只显示前几个),函数正常工作。(2) 测试spcSysCall():test_spcSysCall.c#include#include#include#include#define test_sp
16、cSysCall 319int 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 320int main()syscall(test_clrSysCall);syscall(test_allSysCa
17、ll);return 0;测试结果:所有系统调用执行次数都被清零,除了部分函数立即得到执行,计数为1,函数正常工作。如何验证我的代码1. 进入虚拟机,通过账号root,密码aaasss登录,进入目录/home/testSCcd /home/testSC2. 验证allSysCall()函数(列出所有系统调用执行次数),执行如下命令:gcc -o result_allSysCall test_allSysCall.c (执行test_allSysCall.c代码,生成可执行文件result_allSysCall)./result_allSysCall(运行代码查看执行结果,在这里能看到所有系统调
18、用执行次数)3. 验证clrSysCall()函数(清零所有系统调用执行次数),执行如下命令:gcc o result_clrSysCall test_clrSysCall.c (执行test_clrSysCall.c代码,生成可执行文件result_clrSysCal中)./result_clrSysCall(运行代码查看执行结果,这里能清零所有系统调用执行次数,并查看清零结果)4. 验证spcSysCall()函数(列出特定系统调用执行次数),执行如下命令:gcc -o result_spcSysCall test_spcSysCall.c (执行test_spcSysCall.c代码,生
19、成可执行文件result_spcSysCall)./result_spcSysCall200(运行代码查看执行结果,在这里能看到特定系统调用执行次数,其中200是你想查询的系统调用号,当然也可以输入其他号码,1320皆可)实验一小结本人一直是windows用户,对linxu不甚了解,这次试验我先对linux进行了学习,发现其操作也是挺友好的,试用了几个小时有图形界面的ubuntu之后直接就装上了无界面的CentOS server,发现其使用也不是很困难。在这次试验中加强了我对系统调用的理解。系统调用是用户空间和内核空间的桥梁。用户空间无法进入内核执行内核代码,所以通过软中断的方式告诉内核从而间
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 华南理工大学 作业 报告 19
限制150内