实验二系统调用.docVIP

  • 57
  • 0
  • 约 12页
  • 2016-02-25 发布于江苏
  • 举报
实验二系统调用.doc

实验目的编辑 建立对系统调用接口的深入认识 掌握系统调用的基本过程 能完成系统调用的全面控制 为后续实验做准备 实验内容编辑 此次实验的基本内容是:在Linux 0.11上添加两个系统调用,并编写两个简单的应用程序测试它们。 iam() 第一个系统调用是iam(),其原型为: int iam(const char * name); 完成的功能是将字符串参数name的内容拷贝到内核中保存下来。要求name的长度不能超过23个字符。返回值是拷贝的字符数。如果name的字符个数超过了23,则返回“-1”,并置errno为EINVAL。 在kernal/who.c中实现此系统调用。 whoami() 第二个系统调用是whoami(),其原型为: int whoami(char* name, unsigned int size); 它将内核中由iam()保存的名字拷贝到name指向的用户地址空间中,同时确保不会对name越界访存(name的大小由size说明)。返回值是拷贝的字符数。如果size小于需要的空间,则返回“-1”,并置errno为EINVAL。 也是在kernal/who.c中实现。 测试程序 运行添加过新系统调用的Linux 0.11,在其环境下编写两个测试程序iam.c和whoami.c。最终的运行结果是: $ ./iam lizhijun $ ./whoami lizhijun 实验报告编辑 在实验报告中回答如下问题: 从Linux 0.11现在的机制看,它的系统调用最多能传递几个参数?你能想出办法来扩大这个限制吗? 用文字简要描述向Linux 0.11添加一个系统调用foo()的步骤。 评分标准编辑 将?testlab2.c?在修改过的Linux 0.11上编译运行,显示的结果即内核程序的得分。满分50% 只要至少一个新增的系统调用被成功调用,并且能和用户空间交换参数,可得满分 将脚本?testlab2.sh?在修改过的Linux 0.11上运行,显示的结果即应用程序的得分。满分30% 实验报告,20% 实验提示编辑 首先,请将Linux 0.11的源代码恢复到原始状态。 《注释》的5.5节详细讲述了0.11如何处理系统调用,是非常有价值的参考。 操作系统实现系统调用的基本过程是: 应用程序调用库函数(API); API将系统调用号存入EAX,然后通过中断调用使系统进入内核态; 内核中的中断处理函数根据系统调用号,调用对应的内核函数(系统调用); 系统调用完成相应功能,将返回值存入EAX,返回到中断处理函数; 中断处理函数返回到API中; API将EAX返回给应用程序。 应用程序如何调用系统调用 在通常情况下,调用系统调用和调用一个普通的自定义函数在代码上并没有什么区别,但调用后发生的事情有很大不同。调用自定义函数是通过call指令直接跳转到该函数的地址,继续运行。而调用系统调用,是调用系统库中为该系统调用编写的一个接口函数,叫API(Application Programming Interface)。API并不能完成系统调用的真正功能,它要做的是去调用真正的系统调用,过程是: 把系统调用的编号存入EAX 把函数参数存入其它通用寄存器 触发0x80号中断(int 0x80) 0.11的lib目录下有一些已经实现的API。Linus编写它们的原因是在内核加载完毕后,会切换到用户模式下,做一些初始化工作,然后启动shell。而用户模式下的很多工作需要依赖一些系统调用才能完成,因此在内核中实现了这些系统调用的API。我们不妨看看lib/close.c,研究一下close()的API: #define __LIBRARY__ #include unistd.h _syscall1(int,close,int,fd) 其中_syscall1是一个宏,在include/unistd.h中定义。将_syscall1(int,close,int,fd)进行宏展开,可以得到: int close(int fd) { long __res; __asm__ volatile (int $0x80 : =a (__res) : 0 (__NR_close),b ((long)(fd))); if (__res = 0) return (int) __res; errno = -__res; return -1; } 这就是API的定义。它先将宏__NR_close存入EAX,将参数fd存入EBX,然后进行0x80中断调用。调用返回后,从EAX取出返回值,存入__res,再通过对__re

文档评论(0)

1亿VIP精品文档

相关文档