操作系统原理与实践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

操作系统原理与实践3--系统调用_第1张图片

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

操作系统原理与实践3--系统调用_第2张图片

3.在unistd.h添加_NR_whoami和__NR_iam

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

#define __NR__iam 72
#define __NR__whoami 73

如图
操作系统原理与实践3--系统调用_第3张图片
操作系统原理与实践3--系统调用_第4张图片

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

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

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

然后再拷贝进去,如图:
操作系统原理与实践3--系统调用_第5张图片
随手卸载掉hdc

sudo umount hdc

操作系统原理与实践3--系统调用_第6张图片

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

操作系统原理与实践3--系统调用_第7张图片

6.system_call.s

操作系统原理与实践3--系统调用_第8张图片
由于修改了系统调用总数,令:

nr_system_calls = 74

操作系统原理与实践3--系统调用_第9张图片

7.sys.h

这里需要添加sys_iam和sys_whoami的引用,如图:
操作系统原理与实践3--系统调用_第10张图片

8.实现sys_iam()和sys_whoami()

首先再kernel建立who.c
操作系统原理与实践3--系统调用_第11张图片
模仿sys_close写sys_iam和sys_whoiam:

#define __LIBRARY__
#include 
#include 
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-1;
        return -1;
    }
    else{
        for(i=0;i<=size;i++){
            *(name+i)=sys_name[i];
        }
        return size;
    }
}

操作系统原理与实践3--系统调用_第12张图片

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

操作系统原理与实践3--系统调用_第13张图片

\### 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

操作系统原理与实践3--系统调用_第14张图片

10.尝试编译:

make all

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

#define __LIBRARY__
#include 
#include 
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(sizereturn -1;
    }
    else{
        for(i=0;i<=size;i++){
            *(name+i)=sys_name[i];
        }
        return size;

}

编译成功:
操作系统原理与实践3--系统调用_第15张图片

11.编写测试程序

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

#define __LIBRARY__
#include
#include

_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
#include

_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;
}

测试效果如下:
操作系统原理与实践3--系统调用_第16张图片
这里输出了我的信息,但不能输入。(用printk的时候会发生iam.o文件不能编译的问题,暂时不能解决,用了printf作代替)

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

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

#define _LIBRARY_
#include 
#include 
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"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:
操作系统原理与实践3--系统调用_第17张图片
发现不一致都是大于23个字符时的,因为格式的问题。通过。

test2.sh:
操作系统原理与实践3--系统调用_第18张图片

四、实验总结

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

五、问题回答

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

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

六、附录

最后的who.c文件:

#define __LIBRARY__
#include 
#include 
#include
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"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 
#include 
#include

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 
#include 
#include


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
#include
#include

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

就这样了,好累啊

你可能感兴趣的:(linux内核(操作系统))