系统调用接口

系统调用接口

前言

实验参考蓝桥云操作系统原理与实践_Linux - 蓝桥云课 (lanqiao.cn)
https://www.lanqiao.cn/courses/115?spm=a2c6h.12873639.article-detail.7.7d6e4563wUBwKz
CSDN博主
https://blog.csdn.net/leoabcd12/article/details/119986747
其中代码插入使用的是PPT 和word编辑器
http://word.wd1x.com/
有任何错误请多多指正,祝好!!

一、 实验目的

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

二、 实验内容

此次实验的基本内容是:在 Linux 0.11 上添加两个系统调用,并编写两个简单的应用程序测试它们。
(1)iam()
第一个系统调用是 iam(),其原型为:
int iam(const char * name);
完成的功能是将字符串参数 name 的内容拷贝到内核中保存下来。要求 name 的长度不能超过 23 个字符。返回值是拷贝的字符数。如果 name 的字符个数超过了 23,则返回 “-1”,并置 errno 为 EINVAL。
在 kernal/who.c 中实现此系统调用。
(2)whoami()
第二个系统调用是 whoami(),其原型为:
int whoami(char* name, unsigned int size);

它将内核中由 iam() 保存的名字拷贝到 name 指向的用户地址空间中,同时确保不会对 name 越界访存(name 的大小由 size 说明)。返回值是拷贝的字符数。如果 size 小于需要的空间,则返回“-1”,并置 errno 为 EINVAL。
也是在 kernal/who.c 中实现。
(3)测试程序
运行添加过新系统调用的 Linux 0.11,在其环境下编写两个测试程序 iam.c 和 whoami.c。最终的运行结果是:
$ ./iam lizhijun
$ ./whoami
lizhijun

三、 实验步骤

  1. 实验前准备
    首先通过如下的代码,将oslab文件夹里面的hit-oslab-linux-20110823.tar.gz完成linux环境的搭建
# 进入到 oslab 所在的文件夹  
$ cd /home/shiyanlou/oslab/  
# 解压,并指定解压到 /home/shiyanlou/  
# 这样的话,在 /home/shiyanlou/oslab/ 中就能找到解压后的所有文件  
$ tar -zxvf hit-oslab-linux-20110823.tar.gz \  
  -C /home/shiyanlou/  
# 查看是否解压成功  
$ ls -al  

除了压缩包 hit-oslab-linux-20110823.tar.gz 之外,其他的就是压缩包中的内容
其次,请将 Linux 0.11 的源代码恢复到原始状态。首先输入以下代码将Linux恢复到原始状态

# 删除原来的文件  
$ cd ~/oslab  
$ sudo rm -rf ./*  
# 重新拷贝  
$ cp -r /home/teacher/oslab/* ./  

2. 添加iam和whoami系统调用编号的宏定义(_NR_xxxxxx),文件:include/unistd.h。
点击桌面的【home】【oslab】【Linux 0.11】【include】【unistd.h】,右键打开,在
【#define __NR_setregid 71 】后面加入如下两行代码(如图1所示)

#define __NR_whoami   72
#define __NR_iam   73

在这里插入图片描述
(图1)
3. 修改系统调用总数, 文件:kernel/system_call.s
点击【shiyanlou】【oslab】【linux-0.11】【kernel】,打开system_call.s文件
将nr_system_calls = 72改为nr_system_calls = 74 如图2所示
在这里插入图片描述

(图2)
4. 为新增的系统调用添加系统调用名并维护系统调用表,文件:include/linux/sys.h
【shiyanlou】【oslab】【linux-0.11】【include】,打开sys.h文件,
在extern int sys_setregid(); 后面添加如下的两行代码并将sys_setreuid,改为sys_setregid ,sys_whoami,sys_iam,如图3所示

extern int sys_whoamio;  
extern int sys_iam();  
 

在这里插入图片描述

(图3)
5. 为新增的系统调用编写代码实现,在linux-0.11/kernel目录下,创建一个文件 who.c。
在kernel目录下,右键新建文件文件,文件名为【who.c】,在打开的文件里面输入以下的代码,完成who.c文件的创建,如图4所示。
在这里插入图片描述

(图4)

#include <asm/segment.h>  
#include <errno.h>  
#include <string.h>  
char _myname[24];  
int sys_iam(const char *name)  
{  
   char str[25];  
   int i = 0;  
   do  
    {  
       // get char from user input  
        str[i] = get_fs_byte(name + i);  
    } while (i <= 25 && str[i++] != '\0');  
  
    if (i > 24)  
    {  
        errno = EINVAL;  
        i = -1;  
   }  
    else  
    {  
        // copy from user mode to kernel mode  
        strcpy(_myname, str);  
    }  
  
    return i;  
}  
int sys_whoami(char *name, unsigned int size)  
{  
    int length = strlen(_myname);  
    printk("%s\n", _myname);  
  
    if (size < length)  
    {  
        errno = EINVAL;  
        length = -1;  
    }  
    else  
    {  
        int i = 0;  
        for (i = 0; i < length; i++)  
       {  
            // copy from kernel mode to user mode  
            put_fs_byte(_myname[i], name + i);  
        }  
    }  
    return length;  
}  
  1. 修改 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

(如图6所示)
再者将

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

在这里插入图片描述

(图5修改前)
在这里插入图片描述

(图6第一处修改)
在这里插入图片描述

(图7第二处修改)
添加了who.s who.o: who.c …/include/linux/kernel.h …/include/unistd.h。
7. 编写测试程序
到此为止,内核中需要修改的部分已经完成,接下来需要编写测试程序来验证新增的系统调用是否已经被编译到linux-0.11内核可供调用。首先在oslab目录下编写iam.c,whoami.c。
Iam.c和whoami.c的代码下面所示。

Iam.c
/* iam.c */  
#define __LIBRARY__  
#include <unistd.h>   
#include <errno.h>  
#include <asm/segment.h>   
#include <linux/kernel.h>  
_syscall1(int, iam, const char*, name);       
int main(int argc, char *argv[])  
{  
  /*调用系统调用iam()*/  
    iam(argv[1]);  
    return 0;  
}  

whoami.c
/* whoami.c */  
#define __LIBRARY__  
#include <unistd.h>   
#include <errno.h>  
#include <asm/segment.h>   
#include <linux/kernel.h>  
#include <stdio.h>       
_syscall2(int, whoami,char *,name,unsigned int,size);       
int main(int argc, char *argv[])  
{  
    char username[64] = {0};  
    /*调用系统调用whoami()*/  
    whoami(username, 24);  
    printf("%s\n", username);  
    return 0;  
}  

以上两个文件需要放到启动后的linux-0.11操作系统上运行,验证新增的系统调用是否有效,那如何才能将这两个文件从宿主机转到稍后虚拟机中启动的linux-0.11操作系统上呢?这里我们采用挂载方式实现宿主机与虚拟机操作系统的文件共享,在 oslab 目录下执行以下命令挂载hdc目录到虚拟机操作系统上。
sudo ./mount-hdc
(如图8所示)
在这里插入图片描述

(图8)
再通过以下命令将上述两个文件拷贝到虚拟机linux-0.11操作系统/usr/root/目录下,命令在oslab/目录下执行:
cp iam.c whoami.c hdc/usr/root
如果目标目录下存在对应的两个文件则可启动虚拟机进行测试了。如图9所示
在这里插入图片描述

(图9)
8. 编译
在【oslab】目录下输入./run,在调试的页面中输入以下代码.如图10所示。

[/usr/root]# gcc -o iam iam.c  
[/usr/root]# gcc -o whoami whoami.c  

在这里插入图片描述

(图10)
9. 运行测试
在下面的窗口输入两行代码,点击回车进行运行。如图11所示。

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

在这里插入图片描述

(图11)
10.命令执行后,很可能会报以下错误:
在这里插入图片描述

(图12)
这代表虚拟机操作系统中/usr/include/unistd.h文件中没有新增的系统调用调用号为新增系统调用设置调用号。【oslab】【hdc】【usr】【include】【unistd.h】打开unistd.h加入下面两行代码。

#define __NR_whoami     72  
#define __NR_iam        73  

再次执行:实验成功!

四、 实验总结

在本次实验中也遇到了不少的问题,其中不少部分是在CSDN和老师的指导下完成的,其中主要涉及到最困难的部分是后期编译和调试的时候,失败了好几次,后来通过查阅资料和各种辅助也也顺利完成了实验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值