哈工大李治军老师的操作系统实验之系统调用

实验目标

此次实验的基本内容是:在 Linux 0.11 上添加两个系统调用,并编写两个简单的应用程序测试它们。

  1. 第一个系统调用是 iam(),其原型为:

    int iam(const char * name);
    

    完成的功能是将字符串参数 name 的内容拷贝到内核中保存下来。要求 name 的长度不能超过 23 个字符。返回值是拷贝的字符数。如果 name 的字符个数超过了 23,则返回 “-1”,并置 errno 为 EINVAL。

    kernal/who.c 中实现此系统调用。

  2. 第二个系统调用是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  Linux

$ whoami

Linux

实验过程

1. 理论步骤

系统调用的基本过程如下:

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

2. 看 close()系统调用如何实现

即使看理论依然不会懂什么是系统调用,做这个实验最高效的方法是去仿照其他系统调用,看看其他系统调用是如何实现的。我们还是按照上面系统调用基本过程来分析close()函数(在Linux源代码的lib文件夹下面)

/*
 *  linux/lib/close.c
 *
 *  (C) 1991  Linus Torvalds
 */

#define __LIBRARY__
#include <unistd.h>

_syscall1(int,close,int,fd)

这就是close 系统调用在用户态的API调用形式, 你也许会惊奇,函数名不是 close 啊, 这是一个宏, 用来创建一个函数, 因为在操作系统层面不需要知道你是做什么的,只需要知道系统调用号以及参数,宏负责把这两个东西放到寄存器中,然后通过中断进入内核态,进入到内核态之后通过系统调用号查找系统调用地址,然后结合存储在寄存器当中的参数执行该函数。这个宏定义在unistd.h(在include文件夹下面)。这个是内联汇编形式, 在该文件下,你会发现还有_syscall2 _syscall3等宏定义, 区别在于最后的数字,该数字代表宏定义的函数参数个数。(建议先学习以下内联汇编)

#define _syscall1(type,name,atype,a) \
type name(atype a) \
{
      \
long __res; \
__asm__ volatile ("int $0x80" \
	: "=a" (__res) \
	: "0" (__NR_##name),"b" ((long)(a))); \
if (__res >= 0) \
	return (type) __res
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值