lsj week2 lab1报告

任务为往dragonOS中添加一个系统调用并编写测试程序,这里添加一个对两个数进行相加的系统调用,
首先在kernel/src/syscall/mod.rs中找到这么一段:


可以知道需要添加的系统调用编号至少在这里往上累加:
image
然后在syscall的处理函数中添加对应的系统调用处理逻辑:

这里由于接受的用户态传递的参数类型为usize,且handle的返回类型也为usize,不能处理负数相加的结果(这里使用i32整数类型),读源码查找到SystemError::EOVERFLOW对应数值溢出错误,首先判断传入的参数大小是否超出i32最大值,超出则返回错误,否则返回正常相加结果
然后是编写用户态的测试程序:

extern crate libc;
use libc::syscall;

fn main(){
    let a=-10;
    let b=-20;
    unsafe{
        let sum:i32=syscall(100004,a,b) as i32;
        assert_eq!(sum,a+b,"syscall returns incorrect result");
        println!("syscall returns correct result :{}+{}={}",a,b,sum);
    }
}

这里要注意use libc::syscall需要在Cargo.toml添加依赖,查找其他用户态的测试程序直接照搬:libc = "0.2.153"否则出现报错:


然后对用户态测试程序添加Makefile(首先安装DADK):

# 用户程序名称
name = "test_SYS_ADD"
# 版本号
version = "0.1.0"
# 用户程序描述信息
description = "测试SYS_ADD"
# (可选)默认: false 是否只构建一次,如果为true,DADK会在构建成功后,将构建结果缓存起来,下次构建时,直接使用缓存的构建结果
build-once = false
#  (可选) 默认: false 是否只安装一次,如果为true,DADK会在安装成功后,不再重复安装
install-once = false
# 目标架构
# 可选值:"x86_64", "aarch64", "riscv64"
target-arch = ["x86_64"]
# 任务源
[task-source]
# 构建类型
# 可选值:"build-from_source", "install-from-prebuilt"
type = "build-from-source"
# 构建来源
# "build_from_source" 可选值:"git", "local", "archive"
# "install_from_prebuilt" 可选值:"local", "archive"
source = "local"
# 路径或URL
source-path = "user/apps/test_SYS_ADD"
# 构建相关信息
[build]
# (可选)构建命令
build-command = "make install"
# 安装相关信息
[install]
# (可选)安装到DragonOS的路径
in-dragonos-path = "/"
# 清除相关信息
[clean]
# (可选)清除命令
clean-command = "make clean"
# (可选)依赖项
# 注意:如果没有依赖项,忽略此项,不允许只留一个[[depends]]
# 由于原文件中依赖项为空,此处省略[[depends]]部分
# (可选)环境变量
# 由于原文件中没有环境变量,此处省略[[envs]]部分

最后编译写入镜像运行即可:
image

一点碎碎念:以前做过xv6的lab,系统调用这个算是比较熟悉,但dragonOS的内核编写和测试程序的调用和xv6还是有些区别的,xv6的用户态要调用系统调用需要在用户态注册,然后由这个注册的条目带着参数再转到内核态,但dragonos直接把内核的lib导出,在用户态直接使用syscall,从隔离的角度看起来lib就是内核向用户态提供的接口,而且xv6的系统调用参数都是维护在一张表以内的,可能是教学使用规模确实比较小可以这么做吧,dragonOS的系统调用参数,不同模块的参数表是在不同目录下的,这个lab給加法添加系统调用参数也只是找了个地方加进去

1 个赞

参数表也没有说在不同目录下吧hhh,只是实际执行逻辑在不同的模块下