MIT6.S081操作系统实验——Xv6-and-Unix-utilities
前言
本实验需要编写一些用户程序,执行系统调用来达成目标。作为第一个实验,本次实验内容比较简单,主要内容是展示用户如何调用操作系统的接口,即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
创建子进程。 - 使用
read
和write
对管道进行读和写。 - 使用
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。使用
fork
和exec
函数来执行子进程。
代码
//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 grade
或python ./grade-lab-util
来评测整个实验。
若想单独评测一个题目比如sleep可以使用python ./grade-lab-util sleep
。
评测整个实验前别忘了在Xv6根目录创建一个名为time.txt
的文件,在里面输入一个整数表明自己在这个实验上花了多少个小时。
MIT6.S081操作系统实验——Xv6-and-Unix-utilities相关推荐
- 操作系统lab:Xv6 and Unix utilities
lab1:Xv6 and Unix utilities 实验的主要内容,xv6的系统调用以及实现一些基础的shell操作.实验链接 实验总结 xv6环境配置,教程.注意事项,在配置的过程中出现问题,i ...
- MIT6.S081操作系统实验——操作系统是如何在qemu虚拟机中启动的?
前言 为了更好的理解基于RISC-V体系的Xv6操作系统是如何在qemu中启动的,我将详细地梳理从执行make qemu命令开始到Xv6的shell启动为止的具体流程. 执行make qemu后发生了 ...
- 操作系统实验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 模拟器启 ...
- 6.S081「Xv6 and Unix utilities」
6.S081「Xv6 and Unix utilities」 insorker 2022/2/21 Hello 新学期,新气象,祝看到这篇文章的人一生不患腱鞘炎. Introduction This ...
- Lab: Xv6 and Unix utilities sleeppingpong
实验环境 VMware Ubuntu20.04 + xv6-labs-2021 1. 实验内容与要求 阅读Lab: Xv6 and Unix utilities中的sleep,pingpong两个任务 ...
- xv6---Lab1: Xv6 and Unix utilities
目录 参考资料: 1.1进程和内存 1.2 I/O 和文件描述符 1.3管道 源码: 调试环境搭建 sleep PingPong primes find xargs 参考资料: Lab: Xv6 an ...
- xv6学习笔记——Lab: Xv6 and Unix utilities
文章目录 前言 一.进程与内存 1.1 fork() 1.2 wait() 1.3 exit() 1.4 exec() 前言 最近在学习MIT经典的操作系统课程--xv6操作系统,之前在本科生期间同样 ...
- 6.S081-Lab: Xv6 and Unix utilities 操作系统实验
学习操作系统的时候,买了一本人民邮电出版社的-Operating Systems: Three Easy Pieces 中译版(操作系统导论). 从书中学到了很多关于操作系统的思想,出现一个问题,思考 ...
- Lab01:Xv6 and Unix utilities
实验测试方法 实验的测试方法主要有2个: 进入到Xv6系统中,执行相应的命令 使用实验提供的评分测试 对于单个实验,可以使用 make GRADEFLAGS=application grade其中ap ...
最新文章
- Hankson的趣味题 解题记录
- logback修改日志内容_记一次Logstash日志丢失问题
- 2.5 指数加权平均的偏差修正-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
- 启明云端分享|注意了,ESP-12F和ESP-12S虽然只有一个字母不同,但在选型时,要注意了,ESP-12F底部是有焊盘的!
- html语言中括号怎么打,HTML语言中括号(尖括号)的字符编码
- 大学刚毕业,零基础大数据如何入门?
- Qt之QLineEdit详解(附源码)
- MySql视图view的使用:创建、修改、删除
- 破解软件试用版到期问题通用办法
- Intellij idea破解2017
- php如何除去图片水印,Phpcms v9如何去掉自带水印的解决方法
- 计算机图形学:光线追踪原理(ray tracing)
- 用计算机能算重量加权平均长度吗,利用计算器求平均数检测试题与*
- 泡泡龙游戏c语言程序,七彩泡泡龙小程序-微信七彩泡泡龙小程序小游戏v1.0-游戏宝手游网...
- ssms连接mysql_SQL Server安装以及使用SSMS连接数据库
- 仿微信评论显示更多与收起
- 开源共轴双桨无人机 Tdrone 软硬件全部在 GitHub 开源
- chrome设置微信ua_模拟UA实现访问只能在微信上打开的网页
- Qt开发技术:Qt富文本(三)Qt支持的HTML子集(查询手册)以及涉及的类
- 突破网管的局域网网络限制方法大全
热门文章
- 香港科大汪校长轻松访谈(1)|探秘倪明选校长的人生档案(精编版)
- [发布]箫心Web个人共享服务器2007.1.15.0 DotNetC#2.0开发
- 中国首届原型设计大赛在成都举办
- simulink 求解输入为单位阶跃函数时系统状态方程的值
- 安徽大学计算机系课程表,超智能! 安徽大学新学期 全面启用电子课表
- system(“pause”)作用
- P1058 [NOIP2008 普及组] 立体图
- 20140216技术交流活动总结
- linux无法识别hd4600,HD4600 只有7M 怎么破hd4600
- 2009年IT新潮技术回顾!