实验02-系统调用

94 0

实验内容

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命令,并进入挂载的文件系统内进行编译测试。

发表评论

Scroll Up