操作系统实验之系统调用

在unistd.h中可以看到现在Linux 0.11 支持3个参数的传递。添加参数的方法大概有3条
1. 可以采用ESI,EDI,EBP,ESP这几个寄存器传递参数。
2. 可以采用《Linux 0.11注释》中提到的系统调用门的办法。
3. 可以开辟一块用户态的空间,允许内核态访问,传递参数时,只需传递此空间的首地址指针即可。

向linux 0.11添加一个系统调用foo()的步骤:
首先。在内核中编写系统调用处理函数。
其次。在include/unistd.h中添加系统调用的功能号(#define __NR_foo **)
并且相应的在include/linux/sys.h中声明新的系统调用处理函数以及添加系统 调用处理程序指针数组表中该项的索引值。

在make file中添加新系统调用所在文件的编译、链接规则(依赖关系)。修改system_call.s中系统调用总数。
最后。在应用程序中提供接口,调用系统调用。

这次实验,需要改写unistd.h sys.h system_call.s makefile 4个文件,而且需要自己写出 who.c iam.c whoami.c 3个文件

(1)修改linux-0.11/include/linux/sys.h

根据Linux调用系统调用的过程,需要把 iam()与whoami()两个函数加到全局变量,和中断函数表中就可以了,中断被调用的时候,先查找中断向量表,找到相应的函数名,调用其函数。

分别添加声明到最下面和数组中:
声明分别为extern int sys_iam();extern int sys_whoami();sys_iam, sys_whoami

........................
extern int sys_setreuid();
extern int sys_setregid();

extern int sys_iam();//需要新增的地方
extern int sys_whoami();

fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid,.....................................
sys_setreuid,sys_setregid, ```sys_iam, sys_whoami```};//记得在中断向量表的最后填上系统调用

(2) 修改系统调用数:

system_call.s 在 linux-0.11/kernel 中
需要把nr_system_calls 由72改为 74 表示了中断函数的个数。

nr_system_calls = 74

(3)新增系统调用号:

unistd.h 不能直接在ubantu中修改,

而需要在bochs虚拟机中修改,
在oslab目录中有一个mount-hdc脚本
运行sudo ./mount-hdc 可以把虚拟机硬盘挂载在oslab/hdc 目录下。
(这个也可以实现文件共享)
hdc/usr/include目录下修改unistd.h

#define __NR_setup    0 
...............//省略
#define __NR_setregid    71 
#define __NR_iam    72    /*new system_call 72 and 73*/
#define __NR_whoami    73

增加iam,whoami系统调用号就完成了。

(4)新增who.c文件,实现系统调用的函数

将完成的who.c文件放入linux-0.01/kernel 目录下

#include <string.h>
#include <errno.h>
#include <asm/segment.h>

char msg[24];

int sys_iam(const char * name)
{
    char tep[26];
    int i = 0;
    for(; i < 26; i++)
    {
        tep[i] = get_fs_byte(name+i);
        if(tep[i] == '\0')  break;
    }

    if (i > 23) return -(EINVAL);

    strcpy(msg, tep);
    return i;
}

int sys_whoami(char * name, unsigned int size)
{
    int len = 0;
    for (;msg[len] != '\0'; len++);
    
    if (len > size) 
    {
        return -(EINVAL);
    }
    
    int i = 0;
    for(i = 0; i < size; i++)
    {
        put_fs_byte(msg[i], name+i);
        if(msg[i] == '\0') break;
    }
    return i;
}

(5) 修改Makefile 文件

让我们添加的kernel/who.c可以和其它Linux代码编译链接到一起,必须要修改Makefile文件
Makefile在代码树中有很多,分别负责不同模块的编译工作。我们要修改的是kernel/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

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

(6) 新增iam.c 跟whoami.c文件以测试是否添加系统调用成功:

iam.c

#define __LIBRARY__
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
_syscall1(int,iam,const char*,name)

int main(int argc,char* argv[])
{
    iam(argv[1]);
    return 0;
}

whoami.c

#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <stdio.h>

_syscall2(int, whoami, char*, name, unsigned int, size);

int main(int argc, char ** argv)
{
    char t[30];
    whoami(t, 30);
    printf("%s\n", t);
    return 0;
}
注:这两个C文件是需要在你修改过的linux 0.11版本上编译的,如果嫌在 0.11 里面用vi写代码太烦,可以在虚拟机中写好, 在oslab中运行。

简便的方式是把虚拟机硬盘挂载在oslab/hdc 目录下。

sudo ./mount-hdc 

然后再将文件复制到 oslab/hdc/user/root/下
/user/root/ 就是你的linux 0.11 开机后所在目录

cp iam.c,whoami.c oslab/hdc/user/root/

好了,运行

cd /home/fgx/oslab
./run

(7)编译 iam.c 跟 whoami.c

gcc -o iam iam.c 
gcc -o whoami whoami.c 

验证

[/usr/root]# ./iam zhangshan
[/usr/root]# ./whoami
zhangshan 

原创作者:寒夏凉秋
链接:https://www.jianshu.com/p/5786cd42b152
来源:简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值