添加系统调用实验报告.docx
《添加系统调用实验报告.docx》由会员分享,可在线阅读,更多相关《添加系统调用实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
添加系统调用实验报告
一、构建基本的实验环境
1.1基本实验环境与前提条件
Windows7、Word2010、VmwareWorkStation8.5、AdobeReader
ReadHatLinux9.0,gcc,vi
Linux内核[V2.4.18]
1.2虚拟机的安装及使用
1.3将Linux内核源代码及配置文件传送给虚拟机上的RedHatLinuxV9.0系统
配置网络时遇到这个问题,
DeterminingIPinformationforeth0...failed;nolinkpresent.Checkcable?
通过查找资料发现是系统的Bug,
解决方法如下:
到/etc/sysconfig/network-scripts/ifcfg-eth0
在文件最后一行中加入
check_link_down(){
return1;
}
另外如果存在/etc/sysconfig/networking/profiles/default/ifcfg-eth0文件,则同样在其中加入这一段东西即可,然后重启系统。
设置网络为DHCP,重新启动就可以,啦,直接上图
最后将内核代码下载到/root目录下
二、Linux内核编译、配置与调试
2.1内核配置与编译
2.1.1、解压内核源代码文件
tar-zxflinux-2.4.18.tar.gz
2.1.2、解压后如下
2.1.3、拷贝linux,命名为linux-2.4.18
cp-rlinuxlinux-2.4.18
2.1.4、移动config-2.4.18forMP.txt到linux-2.4.18根目录,替换掉.config
2.1.5、进入linux-2.4.18目录,配置和编译内核模块
makeoldconfig
makedep
makeclean
makebzImage
makemodules
2.2内核安装与测试
2.2.1安装内核映像文件
cparch/i386/boot/bzImage/boot/vmlinux-2.4.18
2.2.2拷贝和安装Linux系统映射文件System.map,并创建其与系统映射文件System.map之间的符号链接
2.2.3执行命令makemodules_install以安装可动态加载的内核模块
2.2.4添加启动项的配置
利用vi编辑器,vigrub.conf
查看/所在的位置,为/dev/sda3
2.2.5reboot重新启动系统,从自己创建的内核启动系统
启动后查看内核
分别用uname–r,和dmesg查看
三、Linux系统调用添加与实现
3.1在内核增加系统调用
3.1.1结构体structsrz_rusage可声明如下:
.
structsrz_rusage{
structtimevalru_utime;/*usertimeused*/
structtimevalru_stime;/*systemtimeused*/
longru_majflt;/*majorpagefaults*/
longru_minflt;/*minorpagefaults*/
longru_nswap;/*swaps*/
};
3.1.2添加到linux-2.4.18/include/linux下的resource.h中
3.1.3添加的系统调用名称为:
intget_process_usage(pid_t,structsrz_rusage*);
参考的getrusage和sys_getrusage的代码在linux-2.4.18/linux/kernel/sys.c下面
3.1.4 分析getrusage()和sys_getrusage()的源代码
1)数据结构rusage在头文件resource.h中定义。
structrusage{
structtimevalru_utime;/*usertimeused*/
structtimevalru_stime;/*systemtimeused*/
longru_maxrss;/*maximumresidentsetsize*/
longru_ixrss;/*integralsharedmemorysize*/
longru_idrss;/*integralunshareddatasize*/
longru_isrss;/*integralunsharedstacksize*/
longru_minflt;/*pagereclaims*/
longru_majflt;/*pagefaults*/
longru_nswap;/*swaps*/
longru_inblock;/*blockinputoperations*/
longru_oublock;/*blockoutputoperations*/
longru_msgsnd;/*messagessent*/
longru_msgrcv;/*messagesreceived*/
longru_nsignals;/*signalsreceived*/
longru_nvcsw;/*voluntarycontextswitches*/
longru_nivcsw;/*involuntary"*/
};
2)函数getrusage()的作用是获取系统资源使用情况。
/*
*Itwouldmakesensetoputstructrusageinthetask_struct,
*exceptthatwouldmakethetask_structbe*reallybig*.After
*task_structgetsmovedintomalloc'edmemory,itwould
*makesensetodothis.Itwillmakemovingtherestoftheinformation
*alotsimpler!
(Whichwe'renotdoingrightnowbecausewe'renot
*measuringthemyet).
*
*ThisisSMPsafe.Eitherwearecalledfromsys_getrusageonourselves
*below(weknowwearen'tgoingtoexit/disappearandonlywechangeour
*rusagecounters),orwearecalledfromwait4()onaprocesswhichis
*eitherstoppedorzombied.Inthezombiedcasethetaskwon'tget
*reapedtillshortlyafterthecalltogetrusage(),inbothcasesthe
*taskbeingexaminedisinafrozenstatesothecounterswon'tchange.
*
*FIXME!
Getthefaultcountsproperly!
*/
intgetrusage(structtask_struct*p,intwho,structrusage*ru)
{
structrusager;
memset((char*)&r,0,sizeof(r));
switch(who){
caseRUSAGE_SELF:
r.ru_utime.tv_sec=CT_TO_SECS(p->times.tms_utime);
r.ru_utime.tv_usec=CT_TO_USECS(p->times.tms_utime);
r.ru_stime.tv_sec=CT_TO_SECS(p->times.tms_stime);
r.ru_stime.tv_usec=CT_TO_USECS(p->times.tms_stime);
r.ru_minflt=p->min_flt;
r.ru_majflt=p->maj_flt;
r.ru_nswap=p->nswap;
break;
caseRUSAGE_CHILDREN:
r.ru_utime.tv_sec=CT_TO_SECS(p->times.tms_cutime);
r.ru_utime.tv_usec=CT_TO_USECS(p->times.tms_cutime);
r.ru_stime.tv_sec=CT_TO_SECS(p->times.tms_cstime);
r.ru_stime.tv_usec=CT_TO_USECS(p->times.tms_cstime);
r.ru_minflt=p->cmin_flt;
r.ru_majflt=p->cmaj_flt;
r.ru_nswap=p->cnswap;
break;
default:
r.ru_utime.tv_sec=CT_TO_SECS(p->times.tms_utime+p->times.tms_cutime);
r.ru_utime.tv_usec=CT_TO_USECS(p->times.tms_utime+p->times.tms_cutime);
r.ru_stime.tv_sec=CT_TO_SECS(p->times.tms_stime+p->times.tms_cstime);
r.ru_stime.tv_usec=CT_TO_USECS(p->times.tms_stime+p->times.tms_cstime);
r.ru_minflt=p->min_flt+p->cmin_flt;
r.ru_majflt=p->maj_flt+p->cmaj_flt;
r.ru_nswap=p->nswap+p->cnswap;
break;
}
returncopy_to_user(ru,&r,sizeof(r))?
-EFAULT:
0;
}
3)sys_getrusage()只是调用了内核函数getrusage(),是内核提供给用户的接口。
asmlinkagelongsys_getrusage(intwho,structrusage*ru)
{
if(who!
=RUSAGE_SELF&&who!
=RUSAGE_CHILDREN)
return-EINVAL;
returngetrusage(current,who,ru);
}
3.2编写应用程序调用该系统(调用)过程
3.2.1在sys.c中添加函数get_process_usage()和系统调用函数sys_get_process_usage()的代码;
目录linux-2.4.18/kernel/sys.c
int get_process_usage(struct task_struct *p,struct srz_rusage *ru)
{
struct srz_rusage r;
memset((char *) &r, 0, sizeof(r));
//比上次的实验报告里,更新的内容
printk(“Theprogram(get_process_usage)issuccessful!
\n”);
r.ru_utime.tv_sec=CT_TO_SECS(p->times.tms_utime);
r.ru_utime.tv_usec=CT_TO_USECS(p->times.tms_utime);
r.ru_stime.tv_sec=CT_TO_SECS(p->times.tms_stime);
r.ru_stime.tv_usec=CT_TO_USECS(p->times.tms_stime);
r.ru_minflt=p->min_flt;
r.ru_majflt=p->maj_flt;
r.ru_nswap=p->nswap;
return copy_to_user(ru,&r,sizeof(r))?
-EFAULT:
0;
}
asmlinkage long sys_get_process_usage(pid_t pid,struct srz_rusage *ru) {
struct task_struct *p;
p=find_task_by_pid(pid);
if(p)
{
return get_process_usage(p,ru);
}
return -EINVAL;
}
3)修改完源程序以后,下一个任务是使Linux内核知道该程序的存在。
为了从已有的内核程序中增加到新的函数的连接,需要编辑两个文件。
第一个要修改的文件是/root/linux-2.4.18/include/asm-i386/unistd.h,该文件中包含了系统调用清单,用来给每个系统调用分配一个唯一的号码。
应该将新的系统调用名称加到清单的最后,并给它分配号码序列中下一个可用的系统调用号。
#define__NR_get_process_usage238
根据上图已知系统调用已经用到了237,我们用238
第二个要修改的文件是:
/root/linux-2.4.18/arch/i386/kernel/entry.S,该文件中有类似[.longSYMBOL_NAME()]的清单,该清单用来对sys_call_table[]数组进行初始化,该数组包含指向内核中每个系统调用的指针。
我们在清单最后添加一行:
.longSYMBOL_NAME(sys_get_process_usage)
编译安装内核以后的启动界面
四、编写程序调用新的系统调用
4.1.1程序一
头文件
//get_process_usag.h
#include
#include
源程序
//get_process_usag.c
#include"get_process_usag.h"
#include
intget(pid_tpid);
intmain(intargc,char*argv[])
{
pid_tpid;
pid=atoi(argv[1]);
get(pid);
return1;
}
intget(pid_tpid)
{
structsrz_rusageru;
longr=0;
if(pid<=0){
printf("\nerror:
Pidmustint!
\n\n");
return0;
}
r=syscall(238,pid,&ru);
if(!
r)
{
printf("ShangRongZhusuccess!
\n\n");
printf("User_time:
\t%dseconds:
%dmseconds\n",ru.ru_utime.tv_sec,ru.ru_utime.tv_usec);
printf("System_time:
\t%dseconds:
%dmseconds\n",ru.ru_stime.tv_sec,ru.ru_stime.tv_usec);
printf("Minlostpage:
\t%d\n",ru.ru_minflt);
printf("Maxlostpage:
\t%d\n",ru.ru_majflt);
printf("Changepagetimes:
\t%d\n",ru.ru_nswap);
}
else
printf("Error,cheakthepid:
\n",r);
}
编译
Gcc–otestsyscallgetpu_syscall.c
执行
./testsyscallpid_no
执行结果
Dmesg查看信息
4.1.2程序二
//get_process_syscall2.c
#include"get_process_usag.h"
#include
#define__NR_get_process_usage238
_syscall2(long,get_process_usage,pid_t,pid,structsrz_rusage*,ru)
intget(pid_tpid);
intmain(intargc,char*argv[])
{
pid_tpid;
pid=atoi(argv[1]);
get(pid);
return1;
}
intget(pid_tpid)
{
structsrz_rusageru;
longr=0;
if(pid<=0){
printf("\nerror:
Pidmustint!
\n\n");
return0;
}
r=get_process_usage(pid,&ru);
if(!
r)
{
printf("ShangRongZhusuccess!
\n\n");
printf("User_time:
\t%dseconds:
%dmseconds\n",ru.ru_utime.tv_sec,ru.ru_utime.tv_usec);
printf("System_time:
\t%dseconds:
%dmseconds\n",ru.ru_stime.tv_sec,ru.ru_stime.tv_usec);
printf("Minlostpage:
\t%d\n",ru.ru_minflt);
printf("Maxlostpage:
\t%d\n",ru.ru_majflt);
printf("Changepagetimes:
\t%d\n",ru.ru_nswap);
}
else
printf("Error,cheakthepid:
\n",r);
}
执行结果如下
编译
Gcc-otestsyscall2getpu_syscall2.c
./testsyscallpid_no
dmesg查看
附件:
源程序一
:
第一种实现方法
//get_process_usag.h
#include
#include
源程序
//get_process_usag.c
#include"get_process_usag.h"
#include
intget(pid_tpid);
intmain(intargc,char*argv[])
{
pid_tpid;
pid=atoi(argv[1]);
get(pid);
return1;
}
intget(pid_tpid)
{
structsrz_rusageru;
longr=0;
if(pid<=0){
printf("\nerror:
Pidmustint!
\n\n");
return0;
}
r=syscall(238,pid,&ru);
if(!
r)
{
printf("ShangRongZhusuccess!
\n\n");
printf("User_time:
\t%dseconds:
%dmseconds\n",ru.ru_utime.tv_sec,ru.ru_utime.tv_usec);
printf("System_time:
\t%dseconds:
%dmseconds\n",ru.ru_stime.tv_sec,ru.ru_stime.tv_usec);
printf("Minlostpage:
\t%d\n",ru.ru_minflt);
printf("Maxlostpage:
\t%d\n",ru.ru_majflt);
printf("Changepagetimes:
\t%d\n",ru.ru_nswap);
}
else
printf("Error,cheakthepid:
\n",r);
}
第二种实现方法
//get_process_usag.h
#include
#include
源程序
//get_process_syscall2.c
#include"get_process_usag.h"
#include
#define__NR_get_process_usage238
_syscall2(long,get_process_usage,pid_t,pid,structsrz_rusage*,ru)
intget(pid_tpid);
intmain(intargc,char*argv[])
{
pid_tpid;
pid=atoi(argv[1]);
get(pid);
return1;
}
intget(pid_t