16271012_雷佳宾 L6 2019-10-27 17:36:38 系统调用
416 0

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

系统调用

操作系统实现系统调用的基本过程是:

  • 应用程序调用库函数(API);
  • API 将系统调用号存入 EAX,然后通过中断调用使系统进入内核态;
  • 内核中的中断处理函数根据系统调用号,调用对应的内核函数(系统调用);
  • 系统调用完成相应功能,将返回值存入 EAX,返回到中断处理函数;
  • 中断处理函数返回到 API 中;
  • API 将 EAX 返回给应用程序。

实验的基本内容

在 Linux 0.11 上添加两个系统调用,并编写两个简单的应用程序测试它们。

  • 修改linux-0.11/include/linux/sys.h,把iam()whoami()两个函数加入到全局变量和中断向量表中。中断被调用的时候,先查中断向量表,找到相应的函数名,调用其函数。
copy
  • 由于新增了两个函数,需要修改linux-0.11/kernel/system_call.s中的nr_system_calls的72 改为 74,表明系统调用总数变成了 74 个
copy
  • 修改unistd.h。注意该文件不能直接在oslab/linux-0.11/include/中修改,而要在虚拟机中修改,在oslab目录下运行sudo ./mount-hdc把虚拟机硬盘挂载在oslab/hdc目录下,在hdc/usr/include目录下修改unistd.h。把两个自定义函数的宏定义在这里:
copy
  • 修改 Makefile

    Makefile 里记录的是所有源程序文件的编译、链接规则,要想让我们添加的kernel/who.c可以和其他 linux 代码编译链接到一起,必须要修改 Makefile 文件。

    打开kernel/Makefile,将下面这段代码

    copy

    改为:

copy

同时,还要将下面这段代码:

copy

改为:

copy

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

如果编译时提示 who.c 有错误,就说明修改生效了。所以,有意或无意地制造一两个错误也 不完全是坏事,至少能证明 Makefile 是对的。

图片描述

  • 编写who.c

    linux-0.11/kernel下新建who.c文件,编写下列内容:

copy

此处get_fs_byte()put_fs_byte()均是按地址位读取,即指针操作,且-EINVAL的含义是:无效的参数。用来指出传递给库函数参数时候的各种问题。

  • 接下来编写iam.cwhoami.c两个文件,注意两个文件需要先mount-hdc,然后放在hdc/usr/root的目录下,这样就可以在启动bochs后看到这两个文件。

  • iam.c

copy
  • whoami.c
copy
  • 测试 testlab2.sh

将脚本 testlab2.sh(在 /home/teacher 目录下) 在修改过的 Linux 0.11 上运行,显示的结果即应用程序的得分。满分 30%

编译并测试:

gcc -o iam iam.c -Wall
gcc -o whoami whoami.c -Wall
./testlab2.sh
copy

图片描述

  • 测试 testlab2.c

testlab2.c(在 /home/teacher 目录下) 在修改过的 Linux 0.11 上编译运行,显示的结果即内核程序的得分。满分 50%

图片描述

实验问题解答:

1. 从 Linux 0.11 现在的机制看,它的系统调用最多能传递几个参数?你能想出办法来扩大这个限制吗?

(1)当应用程序经过库函数向内核发出一个中断调用。其中寄存器eax中存放着系统调用编号,参数可以依次存放在ebx,ecx,edx中。因此从 Linux 0.11 现在的机制看,它的系统调用最多能传递3个参数。为了方便执行,内核源码在include/unistd中定义了宏函数_syscall0(),_syscall1(),_syscall2(),_syscall3()分别表示传递0,1,2,3个参数。前两个参数是系统调用的名称,后面的参数是所携带参数的类型和名称。

(2)若想扩大这个限制,传递多个参数,大块数据给内核,可以考虑传递这块数据的指针值。如系统调用:

copy

其宏形式:

copy

2. 用文字简要描述向 Linux 0.11 添加一个系统调用 foo() 的步骤。

  1. 修改include/unistd.h,在其中加入新的系统调用宏定义:
copy
  1. 修改include/linux/sys.h,在里面加上
copy

并在数组fn_ptr sys_call_table[]中加上一项sys_foo

  1. 修改kernel/system_call.s中的系统调用个数nr_system_calls = 73,即新增一个。
  2. kernel文件中编写实现新加的系统调用函数文件foo.c
  3. 修改kernel/Makefile,修改OBJSDependencies添加新的系统调用,使其在编译linux时编译新加的系统调用。
最新评论
暂无评论~