“操作系统与Linux内核导读(北京航空航天大学)”实验报告

系统调用

1.实验目的

  • 建立对系统调用接口的深入认识;
  • 掌握系统调用的基本过程;
  • 能完成系统调用的全面控制;
  • 为后续实验做准备。

2.提出问题

  • 从 Linux 0.11 现在的机制看,它的系统调用最多能传递几个参数?你能想出办法来扩大这个限制吗?
  • 用文字简要描述向 Linux 0.11 添加一个系统调用 foo() 的步骤。

3.实验准备

实验楼每次启动环境都是原始状态。

#进入oslab
$ cd ~/oslab
# 解压,并指定解压到 /home/shiyanlou/
# 这样的话,在 /home/shiyanlou/oslab/ 中就能找到解压后的所有文件
$ tar -zxvf hit-oslab-linux-20110823.tar.gz -C /home/shiyanlou/
copy

4.实验进行

4.1.添加系统调用时需要修改include/unistd.h文件,使其包含__NR_whoami和__NR_iam,并声明函数原型。

#define __NR_iam 72
#deifne __NR_whoami 73
copy
int iam(const char * name);
int whoami(char * name,unsigned int size);
copy

图片描述

图片描述

4.2. 在kernel/system_call.s中修改系统调用总数

nr_system_calls = 73
copy

图片描述

4.3.在include/linux/sys.h中修改系统调用数组

extern int sys_iam();
extern int sys_whoami();
copy

图片描述

4.4.在/kernel中创建who.c,实现 sys_iam() 和 sys_whoami()

#define __LIBRARY__
#include <errno.h>
#include <asm/segment.h>
#include <unistd.h>

char username[64]={0};

int sys_iam(const char* name){
    int result=0,cnt;
    while(get_fs_byte(result+name) !='\0' && result<64)
        result++;
    if(result>23) 
        return -EINVAL;
    for(cnt=0;cnt<=result;cnt++)
        username[cnt]=get_fs_byte(name+cnt);
    return result;
}

int sys_whoami(char *name, unsigned int size){
    int result=0,cnt;
    while(username[result] !='\0' && result<64)
        result++;
    if(result>size) 
        return -EINVAL;
    for(cnt=0;cnt<=result;cnt++)
        put_fs_byte(username[cnt], name+cnt);
    return result;
}
copy

图片描述

4.4.修改/kernel/Makefile

  1. OBJS中添加who.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
    
    copy

    图片描述

  2. Dependencies中添加

    who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h
    
    copy

    图片描述

Makefile 修改后,和往常一样 make all 就能自动把 who.c 加入到内核中了。

4.5.在linux-0.11下make all

$ make all
copy

图片描述

4.6.要在Ubuntu中访问linux-0.11,所以先在磁盘中挂载虚拟机

sudo ./mount-hdc
copy

图片描述

4.7.将修改好的文件复制到虚拟机中

cp linux-0.11/include/unistd.h hdc/usr/include
cp linux-0.11/include/linux/sys.h hdc/usr/include/linux
copy

图片描述

4.8.在oslab/hdc/usr/root下编写测试程序"iam.c"和"whoami.c"

#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <asm/segment.h>
_syscall1(int, iam, const char*, name);

int main(int argc, char * argv[]){
    if(argc>1 && iam(argv[1])>=0) 
        return 0;
    return -1;
}
copy

图片描述

#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <asm/segment.h>
#include <stdio.h>
_syscall2(int, whoami, char *, name, unsigned int, size);

int main(void){
    char str[64];
    if(whoami(str, 24)<0)
        return -1;
    printf("%s\n",str);
    return 0;
}
copy

图片描述

4.9.将home/teacher/中testlab2.c和testlab2.sh复制到oslab/hdc/usr/root下

图片描述

4.10.取消虚拟机挂载

sudo umount hdc
copy

4.11.在oslab目录下启动bochs

./run
copy

图片描述

4.12.编译

gcc –o testlab2 testlab2.c
gcc -o iam iam.c -Wall
gcc -o whoami whoami.c -Wall
copy

图片描述

4.13.测试testlab2.c

./testlab2
copy

图片描述

4.14.测试自己新增的两个系统调用

./iam bluefly-yyq
./whoami
copy

图片描述

4.15.运行脚本testlab2.sh

./testlab2.sh
copy

图片描述

实验完成。

5.回答问题

  1. 从 Linux 0.11 现在的机制看,它的系统调用最多能传递几个参数?你能想出办法来扩大这个限制吗?
  • 最多能通过ebx,ecx,edx三个寄存器传递参数,即最多三个。
  • 可以通过堆栈来传递参数。
  1. 用文字简要描述向 Linux 0.11 添加一个系统调用 foo() 的步骤。
  • 在include/unistd.h中添加系统调用号__NR_foo,声明函数原型type foo()
  • 在kernel/system_call.s中函数调用总数nr_system_calls数量+1
  • 在include/linux/sys.h中做修改,声明extern int foo();,并在该文件末尾的fn_ptr sys_call_table[]数组中加上一项sys_foo
  • 在linux-0.11/kernel/中创建foo.c,实现sys_foo()函数
  • 在Makefile的OBJS中加入foo.o,并在Dependencies中添加生成foo.s、foo.o的依赖规则
最新评论
暂无评论~