【MIT 6.S081】Lab1: Xv6 and Unix utilities
创始人
2024-05-31 04:35:46
0

Util

  • 概述
  • ```sleep```
  • ```pingpong```
  • ```primes```
  • ```find```
  • ```xargs```

本Lab包括五个应用程序的实现,初步熟悉系统调用接口。
用时约8h(我太菜辣)

本Lab包括五个简单程序的实现,初步熟悉系统调用接口。
笔者用时约6h(我太菜辣)

概述

根据文档说明,我们需要把写的每个程序文件放在user文件夹下,并且在MakeFileUPROGS添加相应的程序名,这样子就可以在qemu中直接用命令行指令调用相应的程序啦。如下图所示。
在这里插入图片描述

sleep

sleep程序接收一个参数,调用库函数sleep进行睡眠即可,没啥好说滴。

#include "kernel/types.h"
#include "user/user.h"int main(int argc, char* argv[]) 
{if (argc != 2) { fprintf(2, "usage: sleep time\n");exit(1);}sleep(atoi(argv[1]));exit(0);
}

pingpong

该程序的要求就是创建一个子进程,父进程为子进程发送一个字节,子进程接收到字节之后,打印ping,向父进程发送一个字节,父进程接收到该字节之后打印pong,程序结束。
做法就是打开两个管道,一个用于父进程写子进程读,另一个则相反。

#include "kernel/types.h"
#include "user/user.h"int main(int argc, char* argv[]) 
{if (argc != 1) { fprintf(2, "usage: pingpong\n");exit(1);}int p_father_to_child[2];int p_child_to_father[2];if (pipe(p_father_to_child) == -1 || pipe(p_child_to_father) == -1) {fprintf(2, "failed to open pipe\n");exit(1);}char buf = 'C';int exit_state = 0;// child processif (fork() == 0) {close(p_father_to_child[1]);close(p_child_to_father[0]);if (read(p_father_to_child[0], &buf, 1) != 1) {fprintf(2, "failed to read pipe in child\n");exit_state = 1;}fprintf(1, "%d: received ping\n", getpid());if (write(p_child_to_father[1], &buf, 1) != 1) {fprintf(2, "failed to write pipe in child\n");exit_state = 1;}exit(exit_state);}// father processclose(p_father_to_child[0]);close(p_child_to_father[1]);if (write(p_father_to_child[1], &buf, 1) != 1) {fprintf(2, "failed to write pipe in parent\n");exit_state = 1;}wait(0);if (read(p_child_to_father[0], &buf, 1) != 1) {fprintf(2, "failed to read pipe in parent\n");exit_state = 1;}fprintf(1, "%d: received pong\n", getpid());exit(exit_state);
}

primes

该题目要求我们写一个并发运行的素数筛,其思想大致如下:
建立若干个进程,前一个进程的输出为后一个进程的输入(用管道进行连接);
第一个进程没有输入,向管道直接输出2~35;第二个进程以第一个进程的输出作为输入(2~35),向终端输出2(素数),并筛掉2的倍数,向下一个管道输出非2倍数的数,以此类推,直到没有数输出为止即可。

#include "kernel/types.h"
#include "user/user.h"#define RD 0
#define WR 1
const uint INT_SIZE = sizeof(int);void getprime(int left_p[]) {// check if there has a primeint prime, i;if (read(left_p[RD], &prime, INT_SIZE) == 0) {close(left_p[RD]);exit(0);}fprintf(1, "prime %d\n", prime);// create the pipe to the right neighborint right_p[2];pipe(right_p);// read the data from left neighborwhile (read(left_p[RD], &i, INT_SIZE) != 0) {if (i % prime != 0) write(right_p[WR], &i, INT_SIZE);}close(left_p[RD]);close(right_p[WR]);if (fork() == 0) {getprime(right_p);} else {close(right_p[RD]);wait(0);}}int main(int argc, char* argv[]) 
{if (argc != 1) { fprintf(1, "usage: primes\n");exit(1);}int p[2], i;pipe(p);for (i = 2; i <= 35; i ++ ) {write(p[WR], &i, INT_SIZE);}close(p[WR]);if (fork() == 0) {getprime(p);} else {close(p[RD]);wait(0);}exit(0);
}

find

该题目要求写一个程序,在指定的目录中查找与给定文件名相同的文件,若查找到了则输出文件路径(从指定目录开始的路径)。
根据提示,查看user/ls.c文件中ls程序的实现,其中使用fstat函数查看当前路径的类型(目录或文件)
类似的,我们实现的文件查找也使用fstat函数判断路径类型,如果当前路径是文件,则与给定的文件名比较(相等则输出);如果当前路径是目录,则遍历目录中的内容进行递归查找(注意不要对...递归)

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"void find_file(char* path, const char* filename) {struct dirent de;struct stat st;int fd;char buf[512], *p;if ((fd = open(path, 0)) < 0) {fprintf(2, "find: cannot open %s\n", path);exit(1);}if (fstat(fd, &st) < 0) {fprintf(2, "find: cannot stat %s\n", path);close(fd);exit(1);}if (st.type == T_FILE) {fprintf(2, "usgae: find  \n");close(fd);exit(1);}if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) {fprintf(2, "find: path too long\n");close(fd);exit(1);}strcpy(buf, path);p = buf + strlen(buf);*p ++ = '/';while (read(fd, &de, sizeof(de)) == sizeof(de)) {if (de.inum == 0) continue;memmove(p, de.name, DIRSIZ);p[DIRSIZ] = 0;if (stat(buf, &st) < 0) {fprintf(2, "find: cannot stat %s\n", buf);continue;}if (st.type == T_FILE) {if (strcmp(p, filename) == 0) fprintf(1, "%s\n", buf);} else if (st.type == T_DIR && strcmp(p, ".") != 0 && strcmp(p, "..") != 0) {find_file(buf, filename);}}close(fd);
}int main(int argc, char* argv[]) 
{if (argc != 3) {fprintf(2, "usgae: find  \n");exit(1);}find_file(argv[1], argv[2]);exit(0);
}

xargs

该题要求实现一个程序,每从标准输入中读取一行,就调用一次命令(参数是命令)。
这个其实不难(但是我一开始把buf开大了,调了一个小时),大概就是从标准输入读取一行,然后分割成若干个命令行参数,创建一个子进程后使用ecex执行命令即可。

#include "kernel/types.h"
#include "kernel/param.h"
#include "user/user.h"#define LINE 1024int read_line(int fd, char* buf, int len) {char* p = buf;int i = 0;while (i < len - 1) {int res = read(fd, p, 1);if (res == -1) return -1;else if (res == 0)break;p ++;i ++;if (*(p - 1) == '\n') break;}*p = 0;return i;
}int main(int argc, char* argv[])
{if (argc == 1) {fprintf(2, "usage: xargs command [args]\n");exit(1);}char* args[MAXARG + 1];memset(args, 0, sizeof args);int args_num = argc - 1;int i, j, k;for (i = 1; i < argc; i ++ )args[i - 1] = argv[i];        char buf[LINE];int res;while ( (res = read_line(0, buf, LINE)) != 0 ) {if (res == -1) {fprintf(2, "xargs: cannot read line from standard input\n");exit(1);}if (buf[res - 1] != '\n' && res == LINE) {fprintf(2, "xargs: line too long\n");exit(1);}// split the argsbuf[-- res] = '\0';i = 0, k = args_num;while (i < res) {if (buf[i] == ' ') i ++;else {j = i;while (j < res && buf[j] != ' ')j ++;// buf[i ~ j - 1] is an argumentif (k == MAXARG) {fprintf(2, "xargs: too many arguments\n");}args[k] = (char*)malloc(sizeof(char) * (j - i + 1));memcpy(args[k], buf + i, j - i);args[k][j - i + 1] = '\0';k ++;i = j;}}if (fork() == 0) {exec(args[0], args);fprintf(2, "xargs: command %s not found\n", args[0]);}wait(0);// free the malloc spacefor (i = args_num; i < k; i ++ ) free(args[i]), args[i] = 0;}exit(0);
}

相关内容

热门资讯

我们的中秋的书籍目录 我们的中秋的书籍目录漫话中秋节/翁偶虹暗冷的月夜/彭燕郊平湖秋月/清代宫廷庆中秋/苑洪琪月亮女神崇拜...
“吃不起的黄金”,日本人抢疯了 (转自:智超讲财商)2025 年,日本大米市场迎来 “黄金时代”。不过,这可不是什么值得庆祝的事,而...
求一个古风的男名,两个字的,听... 求一个古风的男名,两个字的,听起来比较飘的,适合一个刺客,比如,弄影。谢谢!!!“刺风”,含义:刺客...
曾与梁朝伟相恋却被刘嘉玲截胡的... 曾与梁朝伟相恋却被刘嘉玲截胡的曾华倩,如今怎样了?如今的她也找到了属于自己的幸福,虽然没有跟梁朝伟在...
我被父母宠坏了咋办,我00后的... 我被父母宠坏了咋办,我00后的男孩吃不了苦心情不好的时候总是对父母发脾气怎么办?作为成年人,要有主见...
女生的英文名,不要太大众化,最... 女生的英文名,不要太大众化,最好是Z,A,Y,X,N 开头结尾的,要附加中文翻译,多几个吧,好选Ar...
名人成功的故事 名人成功的故事名人成功的故事,有谁知道?同疾病顽强搏斗--霍金 一个聪明、智慧,有着远大理想的年轻人...
请帮忙简要写一写《狼和小羊》的... 请帮忙简要写一写《狼和小羊》的主要内容 是寓言的《狼和小羊》的主要内容 狼和小羊狼来到小溪边,看见小...
我是谁,求大神给答案 我是谁,求大神给答案首先你是你爸妈的儿子,是你朋友的朋友,是你亲戚的亲戚。其次你是世界上独一无二的一...
南非东开普省洪灾死亡人数升至8... 转自:千龙网新华社开普敦6月14日电(记者王雷 王晓梅)南非警察部部长森佐·姆许努14日证实,南非东...
战神三国关羽是什么兵 战神三国关羽是什么兵关羽 攻击距离:4 克制:飞刀兵弓兵武斗兵 生命2300 攻击430 防御4...
蜜蜂蜇人电影的名字 蜜蜂蜇人电影的名字叫《杀人蜂》,(Deadly Wasps), 德国电影。也译作《夺命毒蜂》
冰心短篇小说 冰心短篇小说是《相片》这是冰心30年代的一篇力作.你说的文章是冰心的短篇小说《相片》
“零基础英语到高手网络课程”是... “零基础英语到高手网络课程”是什么意思?主要是用来干什么的?应该是说网络课程的英语学习吧,但个人觉得...
公交乘车路线 公交乘车路线深圳宝安西乡固戍南昌村到宝安图书馆公共汽车不是说在宏基附近吗?怎么在航空路附近了 ?航空...
周艺轩,陈梦瑶公开恋情为什么得... 周艺轩,陈梦瑶公开恋情为什么得不到祝福?因为一开始的时候周艺轩的粉丝不高兴陈梦瑶高调秀恩爱,导致了粉...
产品成本包括哪些内容? 产品成本包括哪些内容?产品成本包括直接材料,直接工资、其他直接支出、制造费用。1、直接材料。直接材料...
AI算不算超级全能后卫 AI算不算超级全能后卫双控卫 但是不能算超级后卫肯定不能算啊 ,得分能力毋庸置疑,可内线不是183就...
求一本电子版《犯罪者与动机》 ... 求一本电子版《犯罪者与动机》 马丁格文写的 不要古文 或 犯罪心理学已发送,注意查收。 发件...
怎样才能让自己开心的去面对每一... 怎样才能让自己开心的去面对每一天呢?我们可以学会控制好自己的心情,让自己开心的去面对自己的每一天我们...