前言

本实验需要编写一些用户程序,执行系统调用来达成目标。作为第一个实验,本次实验内容比较简单,主要内容是展示用户如何调用操作系统的接口,即system call,在下一个实验中将详细展示系统调用的工作流程。

本次实验的学习目标是:

  • 学习并理解用户使用shell执行命令时的具体过程

    • 命令的参数如何被进程使用
  • 对Unix的进程间通信方式之一pipe有基础了解

    • 为什么用户进程要使用OS提供的IPC进行通信?
  • 了解Unix中的file description,理解Unix中”一切皆文件“的理念

  • 初步了解make项目以及Makefile

实验原文:Lab: Xv6 and Unix utilities (mit.edu)

前置工作

进入工作文件夹下,输入以下命令

git checkout util #切换到util分支,对应本实验
git clean -xfd #清除无关文件(未追踪的、忽略的文件和文件夹)
git checkout -b solveutil #新建一个solveutil分支,来记录自己的编程过程

sleep (easy)

任务

写一个用户程序sleep,执行系统调用来实现休眠。

$ make qemu
...
init: starting sh
$ sleep 10
(nothing happens for a little while)
$

提示

  • 观察user/grep.c等文件来学习命令行参数如何传入程序。
  • sleep.c添加进Makefile中的UPROGS。(添加完后点击Makefile右上角图标重新加载make项目才能将sleep.c加入索引)
  • 在用户没有给出sleep的参数时打印错误信息。
  • 使用atoi函数将命令行参数由字符串转为整形。
  • 确保main函数调用了exit函数来退出程序。

源码

//sleep.c
#include "kernel/types.h"
#include "user/user.h"int
main(int argc,char* argv[]){if(argc != 2){fprintf(2, "Usage: sleep ticks\n");//stderr的文件描述符的值为2exit(1);}int ticks = atoi(argv[1]);sleep(ticks);exit(0);
}

pingpong(easy)

任务

写一个用户程序pingpong,实现两个进程间的数据传递。

 $ make qemu...init: starting sh$ pingpong4: received ping3: received pong$

提示

  • 使用pipe建立管道。

关于管道的理解可以看这篇博文:Linux系统编程pipe()

  • 使用fork创建子进程。
  • 使用readwrite对管道进行读和写。
  • 使用getpid获取当前进程的pid。

源码

//pingpong.c
#include "kernel/types.h"
#include "user/user.h"int
main() {int p1[2];//parent->childint p2[2];//child->parentpipe(p1);pipe(p2);if (fork() == 0) {//childchar buffer[] = {'y'};read(p1[0],buffer,sizeof(buffer));fprintf(2,"%d: received ping\n",getpid());write(p2[1],buffer,sizeof(buffer));exit(0);}//parentchar buffer[] = {'x'};write(p1[1],buffer,sizeof(buffer));wait(0);read(p2[0],buffer,sizeof(buffer));fprintf(2,"%d: received pong\n",getpid());exit(0);
}

primes(moderate/hard)

任务

使用管道写一个并发版本的素数筛来找出2~35中的素数。

相关链接:Bell Labs and CSP Threads (swtch.com)

概念图:

$ make qemu
...
init: starting sh
$ primes
prime 2
prime 3
prime 5
prime 7
prime 11
prime 13
prime 17
prime 19
prime 23
prime 29
prime 31
$

提示

  • 请牢记这个题目的要求是通过多线程来加速素数筛,在编写程序时要检查自己的程序是否满足并发,**一定不要在父进程写入所有数字后子进程才开始处理!**即使这样也能通过测试。

  • 请小心关闭进程不需要的文件描述符,否则程序将在第一个进程达到 35 之前耗尽xv6的资源。(及时关闭管道非常重要!!!

  • 当一个进程读取完所有数字后,应该等到所有他的子进程终止才能终止,从而避免产生僵尸进程。(善用ctrl+p

  • 当一个管道的写端被关闭时,对读端进行read会返回0。

  • 写入所有数字后再写入一个0来表示写入完毕,否则子进程无法知道父进程是否写入完毕。采取这种做法是因为执行了fork后父进程才关闭管道写端,子进程并不能感应到管道写端已经关闭了。

源码

//primes.c
#include "kernel/types.h"
#include "user/user.h"int main() {int p1[2];pipe(p1);int i;for (i = 2; i <= 35; i++) {write(p1[1], &i, sizeof(i));}i = 0;write(p1[1], &i, sizeof(i));while (1) {int n, prime, p2[2];pipe(p2);read(p1[0], &prime, sizeof(prime));printf("prime %d\n", prime);if (read(p1[0], &n, sizeof(n)) && n) {if (fork() == 0) {//子进程会复制一遍父进程的两个管道,其中父进程用来与祖父进程交流的管道应该被关闭close(p1[0]);close(p1[1]);p1[0] = p2[0];p1[1] = p2[1];continue;}do {if (n % prime != 0)write(p2[1], &n, sizeof(n));} while (read(p1[0], &n, sizeof(n)) && n);write(p2[1], &n, sizeof(n));}//关闭占用的管道close(p1[0]);close(p1[1]);close(p2[0]);close(p2[1]);break;}wait(0);exit(0);
}

find(moderate)

任务

写一个简单版本的UNIX find程序,ls path filename为寻找目录path下所有文件名为filename的文件并输出。

$ make qemu
...
init: starting sh
$ echo > b
$ mkdir a
$ echo > a/b
$ find . b
./b
./a/b
$

提示

  • 查看user/ls.c中的代码来学习如何读取文件夹。
  • 使用递归来实现遍历所有子目录。
  • 不要递归进入.(即当前目录)和..(即父目录)
  • 请使用strcmp函数而非==

源码

//find.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"
#include "kernel/fcntl.h"char *target;/*读取path中的文件名*/
char *
filename(char *path) {char *p = path;while (*p)p++;while (*p != '/' && p != path)p--;return p == path ? p : ++p;
}void
find(char *path) {int fd;struct stat st;struct dirent de;char buf[512], *p;if ((fd = open(path, O_RDONLY)) < 0) {fprintf(2, "find: cannot open %s\n", path);return;}if (fstat(fd, &st) < 0) {fprintf(2, "find: cannot stat %s\n", path);close(fd);return;}switch (st.type) {case T_FILE:if (strcmp(filename(path), target) == 0) {printf("%s\n", path);}break;case T_DIR:if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) {printf("find: path too long\n");break;}strcpy(buf, path);p = buf + strlen(buf);*p++ = '/';while (read(fd, &de, sizeof(de)) == sizeof(de)) {if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0)continue;memmove(p, de.name, DIRSIZ);p[DIRSIZ] = 0;find(buf);}break;}close(fd);
}int
main(int argc, char *argv[]) {if (argc != 3) {fprintf(2, "Usage: find path filename\n");exit(1);}target = argv[2];find(argv[1]);exit(0);
}

xargs(moderate)

任务

写一个简单版本的UNIX xargs程序,从STDIN逐行读取,将每一行作为参数执行命令。比如echo hello too | xargs echo bye,要输出bye hello too,等价于echo bye hello too,建议看原文理解。

提示

  • 使用gets函数来读取STDIN。

  • 使用forkexec函数来执行子进程。

代码

//xargs.c
#include "kernel/types.h"
#include "user/user.h"int
main(int argc, char *argv[]) {char buf[64], *xargs[32];for (int i = 1; i < argc; i++)xargs[i - 1] = argv[i];while (1) {int x = argc - 1;gets(buf, 64);if (buf[0] == 0)break;xargs[x++] = buf;for (char *p = buf; *p; p++) {if (*p == ' ') {*p = 0;xargs[x++] = p + 1;} else if (*p == '\n') {*p = 0;}}if (fork() == 0) {exec(argv[1], xargs);}}wait(0);exit(0);
}

评测

输入make gradepython ./grade-lab-util来评测整个实验。

若想单独评测一个题目比如sleep可以使用python ./grade-lab-util sleep

评测整个实验前别忘了在Xv6根目录创建一个名为time.txt的文件,在里面输入一个整数表明自己在这个实验上花了多少个小时。

MIT6.S081操作系统实验——Xv6-and-Unix-utilities相关推荐

  1. 操作系统lab:Xv6 and Unix utilities

    lab1:Xv6 and Unix utilities 实验的主要内容,xv6的系统调用以及实现一些基础的shell操作.实验链接 实验总结 xv6环境配置,教程.注意事项,在配置的过程中出现问题,i ...

  2. MIT6.S081操作系统实验——操作系统是如何在qemu虚拟机中启动的?

    前言 为了更好的理解基于RISC-V体系的Xv6操作系统是如何在qemu中启动的,我将详细地梳理从执行make qemu命令开始到Xv6的shell启动为止的具体流程. 执行make qemu后发生了 ...

  3. 操作系统实验Lab 1:Xv6 and Unix utilities(MIT 6.S081 FALL 2020)

    Lab 1 Xv6 and Unix utilities 实验要求链接 Boot xv6 (easy) 实验目的 切换到 xv6-labs-2020 代码的 util 分支,并利用 QEMU 模拟器启 ...

  4. 6.S081「Xv6 and Unix utilities」

    6.S081「Xv6 and Unix utilities」 insorker 2022/2/21 Hello 新学期,新气象,祝看到这篇文章的人一生不患腱鞘炎. Introduction This ...

  5. Lab: Xv6 and Unix utilities sleeppingpong

    实验环境 VMware Ubuntu20.04 + xv6-labs-2021 1. 实验内容与要求 阅读Lab: Xv6 and Unix utilities中的sleep,pingpong两个任务 ...

  6. xv6---Lab1: Xv6 and Unix utilities

    目录 参考资料: 1.1进程和内存 1.2 I/O 和文件描述符 1.3管道 源码: 调试环境搭建 sleep PingPong primes find xargs 参考资料: Lab: Xv6 an ...

  7. xv6学习笔记——Lab: Xv6 and Unix utilities

    文章目录 前言 一.进程与内存 1.1 fork() 1.2 wait() 1.3 exit() 1.4 exec() 前言 最近在学习MIT经典的操作系统课程--xv6操作系统,之前在本科生期间同样 ...

  8. 6.S081-Lab: Xv6 and Unix utilities 操作系统实验

    学习操作系统的时候,买了一本人民邮电出版社的-Operating Systems: Three Easy Pieces 中译版(操作系统导论). 从书中学到了很多关于操作系统的思想,出现一个问题,思考 ...

  9. Lab01:Xv6 and Unix utilities

    实验测试方法 实验的测试方法主要有2个: 进入到Xv6系统中,执行相应的命令 使用实验提供的评分测试 对于单个实验,可以使用 make GRADEFLAGS=application grade其中ap ...

最新文章

  1. Hankson的趣味题 解题记录
  2. logback修改日志内容_记一次Logstash日志丢失问题
  3. 2.5 指数加权平均的偏差修正-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  4. 启明云端分享|注意了,ESP-12F和ESP-12S虽然只有一个字母不同,但在选型时,要注意了,ESP-12F底部是有焊盘的!
  5. html语言中括号怎么打,HTML语言中括号(尖括号)的字符编码
  6. 大学刚毕业,零基础大数据如何入门?
  7. Qt之QLineEdit详解(附源码)
  8. MySql视图view的使用:创建、修改、删除
  9. 破解软件试用版到期问题通用办法
  10. Intellij idea破解2017
  11. php如何除去图片水印,Phpcms v9如何去掉自带水印的解决方法
  12. 计算机图形学:光线追踪原理(ray tracing)
  13. 用计算机能算重量加权平均长度吗,利用计算器求平均数检测试题与*
  14. 泡泡龙游戏c语言程序,七彩泡泡龙小程序-微信七彩泡泡龙小程序小游戏v1.0-游戏宝手游网...
  15. ssms连接mysql_SQL Server安装以及使用SSMS连接数据库
  16. 仿微信评论显示更多与收起
  17. 开源共轴双桨无人机 Tdrone 软硬件全部在 GitHub 开源
  18. chrome设置微信ua_模拟UA实现访问只能在微信上打开的网页
  19. Qt开发技术:Qt富文本(三)Qt支持的HTML子集(查询手册)以及涉及的类
  20. 突破网管的局域网网络限制方法大全

热门文章

  1. 香港科大汪校长轻松访谈(1)|探秘倪明选校长的人生档案(精编版)
  2. [发布]箫心Web个人共享服务器2007.1.15.0 DotNetC#2.0开发
  3. 中国首届原型设计大赛在成都举办
  4. simulink 求解输入为单位阶跃函数时系统状态方程的值
  5. 安徽大学计算机系课程表,超智能! 安徽大学新学期 全面启用电子课表
  6. system(“pause”)作用
  7. P1058 [NOIP2008 普及组] 立体图
  8. 20140216技术交流活动总结
  9. linux无法识别hd4600,HD4600 只有7M 怎么破hd4600
  10. 2009年IT新潮技术回顾!