首页 > 其他分享 >OS Lab 1.2 sleep (easy)

OS Lab 1.2 sleep (easy)

时间:2022-11-25 14:08:43浏览次数:33  
标签:调用 函数 程序 参数 user easy sleep OS


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)



标签:调用,函数,程序,参数,user,easy,sleep,OS
From: https://blog.51cto.com/u_15891283/5886613

相关文章