返回

OS Lab 1.2 sleep (easy)

发布时间:2023-09-08 12:16:04 248


1

实验目的


    为 xv6 系统实现 UNIX 的 sleep 程序。你的 sleep 程序应该使当前进程暂停相应的时钟周期数,时钟周期数由用户指定。例如执行 sleep 100 ,则当前进程暂停,等待 100 个时钟周期后才继续执行。



2

实验要求及提示


  • 如果系统没有安装 vim 的请先使用命令 sudo apt install vim 安装 vim 编辑器。
  • 在开始实现程序前,阅读配套教材的第一章,其内容与实验内容息息相关。
  • 实现的程序应该命名为 sleep.c 并最后放入 user 目录下。
  • 可以查看 user 目录下的其他程序(如echo.c、grep.c和rm.c),以它们为参考,了解如何获取和传递给程序相应的命令行参数。
  • 如果用户传入参数有误,即没有传入参数或者传入多个参数,程序应该能打印出错误信息。
  • C 语言中的 atoi 函数可以将字符串转换为整数类型,在 xv6 中也已经定义了相同功能的函数。可以参考 user/ulib.c 或者参考机械工业出版社的《C程序设计语言(第2版·新版)》附录B.5。
  • 使用系统调用 sleep
  • 确保 main 函数调用 exit() 以退出程序。
  • 将你的 sleep 程序添加到 Makefile 的 UPROGS 中。只有这步完成后, make qemu 才能编译你写的程序。
  • 完成上述步骤后,运行 make qemu 编译运行 xv6 ,输入 sleep 10 进行测试,如果 shell 隔了一段时间后才出现命令提示符,则证明你的结果是正确的,可以退出 xv6 运行 ./grade-lab-util sleep 或者 make GRADEFLAGS=sleep grade 进行单元测试。


3

实验思路


  1. 参考 user 目录下的其他程序,先把头文件引入,即 kernel/types.h 声明类型的头文件和 user/user.h 声明系统调用函数和 ulib.c 中函数的头文件。
  2. 编写 main(int argc,char* argv[]) 函数。其中,参数 argc 是命令行总参数的个数,参数 argv[] 是 argc 个参数,其中第 0 个参数是程序的全名,其他的参数是命令行后面跟的用户输入的参数。
  3. 首先,编写判断用户输入的参数是否正确的代码部分。只要判断命令行参数不等于 2 个,就可以知道用户输入的参数有误,就可以打印错误信息。但我们要如何让命令行打印出错误信息呢?我们可以参考 user/echo.c ,其中可以看到程序使用了 write() 函数。 write(int fd, char *buf, int n) 函数是一个系统调用,参数 fd 是文件描述符,0 表示标准输入,1 表示标准输出,2 表示标准错误。参数 buf 是程序中存放写的数据的字符数组。参数 n 是要传输的字节数,调用 user/ulib.c 的 strlen() 函数就可以获取字符串长度字节数。通过调用这个函数,就能解决输出错误信息的问题啦。认真看了提示给出的所有文件代码你可能会发现,像在 user/grep.c 打印信息调用的是 fprintf() 函数,当然,在这里使用也没有问题,毕竟 fprintf() 函数最后还是通过系统调用 write() 。最后系统调用 exit(1) 函数使程序退出。按照惯例,返回值 0 表示一切正常,而非 0 则表示异常。
  4. 接下来获取命令行给出的时钟周期,由于命令行接收的是字符串类型,所以先使用 atoi() 函数把字符串型参数转换为整型。
  5. 调用系统调用 sleep 函数,传入整型参数,使计算机程序(进程、任务或线程)进入休眠。
  6. 最后调用系统调用 exit(0) 使程序正常退出。
  7. 在 Makefile 文件中添加配置,照猫画虎,在 UPROGS 项中最后一行添加 $U/_sleep\ ,最后这项配置如下。
UPROGS=\
$U/_cat\
$U/_echo\
$U/_forktest\
$U/_grep\
$U/_init\
$U/_kill\
$U/_ln\
$U/_ls\
$U/_mkdir\
$U/_rm\
$U/_sh\
$U/_stressfs\
$U/_usertests\
$U/_grind\
$U/_wc\
$U/_zombie\
$U/_sleep\



4

实验代码


// Lab Xv6 and Unix utilities
// sleep.c
// 引入声明类型的头文件
#include "kernel/types.h"
// 引入声明系统调用和 user/ulib.c 中其他函数的头文件
#include "user/user.h"
// int main(int argc,char* argv[])
// argc 是命令行总的参数个数
// argv[] 是 argc 个参数,其中第 0 个参数是程序的全名,以后的参数是命令行后面跟的用户输入的参数
int
main(int argc, char *argv[])
{
// 如果命令行参数不等于2个,则打印错误信息
if (argc != 2)
{
// 系统调用 write(int fd, char *buf, int n) 函数输出错误信息
// 参数 fd 是文件描述符,0 表示标准输入,1 表示标准输出,2 表示标准错误
// 参数 buf 是程序中存放写的数据的字符数组
// 参数 n 是要传输的字节数
// 所以这里调用 user/ulib.c 的 strlen() 函数获取字符串长度字节数
write(2, "Usage: sleep time\n", strlen("Usage: sleep time\n"));
// 当然这里也可以使用 user/printf.c 中的 fprintf(int fd, const char *fmt, ...) 函数进行格式化输出
// fprintf(2, "Usage: sleep time\n");
// 退出程序
exit(1);
}
// 把字符串型参数转换为整型
int time = atoi(argv[1]);
// 调用系统调用 sleep 函数,传入整型参数
sleep(time);
// 正常退出程序
exit(0);
}



5

实验结果


在 xv6 中输入命令后一切符合预期。

$ sleep 10
$ sleep 1 1
Usage: sleep time
$ sleep
Usage: sleep time


退出 xv6 运行单元测试。

./grade-lab-util sleep


提示:如果运行测试报错,先使用命令  vim grade-lab-util  修改 grade-lab-util 文件,把第一行改为  #!/usr/bin/env python3


通过测试样例。

make: 'kernel/kernel' is up to date.
== Test sleep, no arguments == sleep, no arguments: OK (0.9s)
== Test sleep, returns == sleep, returns: OK (1.4s)
== Test sleep, makes syscall == sleep, makes syscall: OK (0.9s)



特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
LeetCode 204.计数质数(简单) 2023-09-08 09:18:19