操作系统实验02-系统调用
实验内容
1.添加系统调用
在 Linux 0.11 上添加两个系统调用,并编写两个简单的应用程序测试它们:
- 第一个系统调用是 iam(),其原型为:
int iam(const char * name);
- 第二个系统调用是 whoami(),其原型为:
int whoami(char* name, unsigned int size);
- 运行添加过新系统调用的 Linux 0.11,在其环境下编写两个测试程序 iam.c 和 whoami.c。
2.回答问题
- 从 Linux 0.11 现在的机制看,它的系统调用最多能传递几个参数?你能想出办法来扩大这个限制吗?
- 用文字简要描述向 Linux 0.11 添加一个系统调用 foo() 的步骤。
实验步骤
1.添加宏定义
首先挂载文件系统,然后在此文件系统内进行编辑
挂载命令:sudo ./mount-hdc
首先找到unistd.h头文件,此文件在include子目录内

打开它并在宏定义出追加 __NR_whoami 和 __NR_iam 两个宏,追加后的效果如下

2.添加用户空间接口函数
在挂载的文件系统内任意位置新增以下两个文件
iam()函数文件
#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
_syscall1(int,iam,const char*,name)
int main(int argc,char* argv[])
{
if(argc<=1)
{
printf("NO Input!(>_<)(>_<)(>_<)\n");
return -1;
}
else
{
if(iam(argv[1])<0)
{
printf(".........Sys Call Exception!(>_<)\n");
return -1;
}
}
return 0;
}
whoami()函数文件
#define __LIBRARY__
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#define N 256
_syscall2(int,whoami,char*,name,unsigned int,size)
int main()
{
int num;
char temp[N]= {0};
num=whoami(temp,N);
if(num >= 0)
{
printf("%s\n",temp);
}
else
{
printf("num <0 System Call Exception!(>_<)");
return -1;
}
return 0;
}
新增完成后执行** sudo umount hdc**解除文件系统的挂载
3.修改system_call.s文件
修改系统调用总数

4.修改sys.h文件
在函数表内增加两个引用,位置需要一一对应。
extern int sys_whoami();
extern int sys_iam();
效果如下

sys_call_table数组内加入sys_whoami和sys_iam,注意顺序一致
5.创建who.c文件
每个系统调用都有一个 sys_xxxxxx() 与之对应,所以增加的两个函数调用也需要有这种函数与其对应
#define __LIBRARY__
#include <unistd.h>
#include <asm/segment.h>
#include <errno.h>
char mem[80]= {0};
int sys_iam(const char* name)
{
int i=0;
int j=0;
while(get_fs_byte(name+i)!='\0')
{
i++;
}
if(i>=24)
{
return -EINVAL;
}
else
{
printk("strlen(%s) = %d\n",mem,i);
}
while((mem[j]=get_fs_byte(name+j))!='\0')
{
j++;
}
return j;
}
int sys_whoami(char* name,unsigned int size)
{
int i=0;
int j=0;
while (mem[i]!='\0')
{
i++;
}
if (i>size)
{
return -1;
}
while(mem[j]!='\0')
{
put_fs_byte(mem[j],(name+j));
j++;
}
return j;
}
将这个文件保存在kernel文件夹下
6.修改Makefile文件
找到如下内容
OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o
并更改为
OBJS = sched.o system_call.o traps.o asm.o fork.o \
panic.o printk.o vsprintf.o sys.o exit.o \
signal.o mktime.o who.o
找到如下内容
### Dependencies:
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h
并更改为
### Dependencies:
who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \
../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \
../include/asm/segment.h
修改完成后执行make命令即可。

7.运行更改后的系统
在oslab根目录内输入./run命令进行调试
然后进入iam.c和whoami.c的目录执行下列命令
gcc iam.c -o iam
gcc whoami.c -o whoami
最后执行可执行文件iam和whoami进行测试
iam测试结果如下:

whoami测试结果如下:

实验报告
问题一
Linux-0.11的系统调用通过寄存器ebx、ecx、edx传递参数,最多能传递3个参数。
扩大传递参数的数量的方法:
- 增加传参所用的寄存器;
- 利用自定义的结构体辅助参数的传递(c语言结构体);
- 将寄存器拆分为高位和低位传递一直比较小的参数;
- 利用堆栈传递参数。
问题二
1.在include/unistd.h中定义宏__NR_foo,并添加供用户调用的函数声明void foo();
2.修改kernel/system_call.s中的nr_system_calls,增加新的系统调用;
3.在include/linux/sys.h中添加函数声明extern void sys_foo(),在系统调用入口表fn_ptr末端添加元素sys_foo;
4.添加kernel/foo.c文件,实现sys_foo()函数;
5.修改kernel/Makefile,在OBJS中加入foo.o,并添加生成foo.s、foo.o的依赖规则;
6.重新执行make命令,并进入挂载的文件系统内进行编译测试。

浙公网安备 33010602011771号