操作系统原理与实践3--系统调用

题目来自:https://www.shiyanlou.com/courses/115/labs/569/document

操作系统原理与实践”实验报告

系统调用

实验报告

一、实验目的

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

二、实验内容

在kernal/who.c中实现iam()的系统调用。
在kernal/who.c中实现whoami()的系统调用。
测试程序,得到一下结果:
\$ ./iam lizhijun
\$ ./whoami
lizhijun

三、实验操作

1准备实验环境

cd ~/oslab
tar zxvf hit-oslab-linux-20110823.tar.gz

实验楼

2.以close.c为例,查看unistd.h的内容

实验楼

3.在unistd.h添加_NR_whoami和__NR_iam

从中可以看到已经排到了71号,那么继续排:

#define __NR__iam 72
#define __NR__whoami 73

如图
实验楼
实验楼

4.导入unistd.h到用户硬盘中

首先要进入linux-0.11目录make all,然后sudo

cd linux-0.11/
make all
cd ..
sudo ./mount-hdc

然后再拷贝进去,如图:
实验楼
随手卸载掉hdc

sudo umount hdc

实验楼

5.查看main.c,sched.c,system.h等内容

实验楼

6.system_call.s

实验楼
由于修改了系统调用总数,令:

nr_system_calls = 74

实验楼

7.sys.h

这里需要添加sys_iam和sys_whoami的引用,如图:
实验楼

8.实现sys_iam()和sys_whoami()

首先再kernel建立who.c
实验楼
模仿sys_close写sys_iam和sys_whoiam:

#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
char sys_name[25];

int sys_iam(const char * name){
    int count=0;
    while(*(name+count)!='\0'){
        count++;
    }
    if(count>23){
        errno=ENIVAL;
        return -1;
    }
    else{
        for(int i=0;i<=count;i++){
            sys_name[i]=*(name+i);
        }
        return count;
    }
}

int sys_whoami(char* name, unsigned int size){
    int i=0;
    while(sys_name[i]!='\0'){
        i++
    }
    if(size<i){
        errno=-1;
        return -1;
    }
    else{
        for(i=0;i<=size;i++){
            *(name+i)=sys_name[i];
        }
        return size;
    }
}

实验楼

9.修改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

实验楼

10.尝试编译:

make all

发生了错误。修改who.c的内容,并加入printk():

#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
char sys_name[25];

int sys_iam(const char * name){
    int i=0;
    int count=0;
    while(*(name+count)!='\0'){
        count++;
    }
    if(count>23){
        errno=EINVAL;
        return -1;
    }
    else{
        for(i=0;i<=count;i++){
            sys_name[i]=*(name+i);
        }
        return count;
    }
}

int sys_whoami(char* name, unsigned int size){
    int i=0;
    while(sys_name[i]!='\0'){
        i++
    }
    if(size<i){
        errno=EINVAL;
        return -1;
    }
    else{
        for(i=0;i<=size;i++){
            *(name+i)=sys_name[i];
        }
        return size;

}

编译成功:
实验楼

11.编写测试程序

在hdc/user/root下编写iam.c,whoami.c:
iam.c:

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

_syscall1(int,iam,const char*,name)
int main(int argc, char* argv[]){
    if(argc<0){
        printf("No Name!");
    }
    else{
        printf("Please input your name:");
        iam(argv[1]);
    }
    return 0;
}

whoiam.c:

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

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

int main(int argc,char* argv[]){
    char name[24]={0};
    whoami(name,24);
    printf("my name is %s",name);
    return 0;
}

测试效果如下:
实验楼
这里输出了我的信息,但不能输入。(用printk的时候会发生iam.o文件不能编译的问题,暂时不能解决,用了printf作代替)

12.实现和用户空间的数据交换

从文档可以看出需要使用get_fs_byte和put_fs_byte来与用户空间交互,于是修改who.c中的代码:

#define _LIBRARY_
#include <unistd.h>
#include <errno.h>
char sys_name[25];

int sys_iam(const char * name){
    int i=0;
    int count=0;
    while(get_fs_byte(name+count)!='\0'){

        count++;
    }
    if(count>23){
        errno=EINVAL;
        printk("string is too long");
        return -1;
    }
    else{
        for(i=0;i<=count;i++){
            sys_name[i]=*(name+i);
        }
        printk("copy finished");
        return count;
    }
}

int sys_whoami(char* name, unsigned int size){
    int i=0;
    while(sys_name[i]!='\0'){
        i++;
    }
    if(size<i){
        errno=EINVAL;
        printk("size is not enough");
        return -1;
    }
    else{
        for(i=0;i<=size;i++){
            put_fs_byte(sys_name[i],(name+i));
        }
        printk("copy finished");
        return size;
    }
}

13.使用测试程序运行

test2.c:
实验楼
发现不一致都是大于23个字符时的,因为格式的问题。通过。

test2.sh:
实验楼

四、实验总结

这次实验遇到了太多麻烦,尤其这个编译很麻烦,每次hdc还要mount很多次才能完成,最终还是参考了别人的实验报告,并进行理解才能完成。非常心累。

五、问题回答

从Linux 0.11现在的机制看,它的系统调用最多能传递几个参数?你能想出办法来扩大这个限制吗?
3个吧,因为最多就是syscall3。如果要更多的话就定义syscall4,styscall5之类的,以满足更多参数调用的需求。

用文字简要描述向Linux 0.11添加一个系统调用foo()的步骤。
调整unistd.h中的内容,比如加NR什么的,并改系统调用的总数等内容->添加系统调用的引用->实现最后的sys_xxx->修改makefile的过程,最后进行编译即可。

六、附录

最后的who.c文件:

#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include<asm/segment.h>
char sys_name[25]={0};

int sys_iam(const char * name){
    int i=0;
    int count=0;
    while(get_fs_byte(name+count)!='\0'&&count<25){

        count++;
    }
    if(count>23){
        errno=EINVAL;
        printk("string is too long");
        return -1;
    }
    else{
        for(i=0;i<=count;i++){
            sys_name[i]=get_fs_byte(name+i);
        }
        printk("copy finished");
        return count;
    }
}

int sys_whoami(char* name, unsigned int size){
    int i=0;
    int rs=0;
    while(sys_name[i]!='\0'&&i<25){
        i++;
    }
    if(size<i){
        errno=EINVAL;
        printk("size is not enough");
        return -1;
    }
    else{
        for(rs=0;rs<=i;rs++){
            put_fs_byte(sys_name[rs],(name+rs));
        }
        printk("copy finished");
        return i;
    }
}

最后的iam.c:

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

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

最后的whoami.c:

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


int main(int argc,char* argv[]){
    char name[100]={0};
    if(whoami(name,24)<0)
        return -1;
    else
        printf("%s\n",name);
    return 0;
}

最后的name.h:

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

_syscall1(int,iam, const char*, name)
_syscall2(int,whoami,char*,name,unsigned int,size)

就这样了,好累啊

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【实验目的】 1. 了解文件系统原理; 2. 用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。 【实验准备】 1.文件的逻辑结构  顺序文件  索引文件  索引顺序文件  直接文件和哈希文件 2.外存分配方式  连续分配  链接分配  索引分配 【实验内容】 1. 实验要求 要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。 2. 实验题目  设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。  程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。  为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。 因系统小,文件目录的检索使用了简单的线性搜索。文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。程序中使用的主要设计结构如下:主文件目录和用户文件目录( MFD、UFD)打开文件目录( AFD)(即运行文件目录)。 M D F 用户名 文件目录指针 用户名 文件目录指针 U F D 文件名 保护码 文件长度 文件名 A F D 打开文件名 打开保护码 读写指针

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值