MIT 6s081 lab1:Xv6 and Unix utilities

Lab1: Xv6 and Unix utilities

作业网址:https://pdos.csail.mit.edu/6.828/2020/labs/util.html

Boot xv6(easy)

下载,启动xv6系统

$ git clone git://g.csail.mit.edu/xv6-labs-2020
Cloning into 'xv6-labs-2020'...
...
$ cd xv6-labs-2020
$ git checkout util
Branch 'util' set up to track remote branch 'util' from 'origin'.
Switched to a new branch 'util'
Build and run xv6:
$ make qemu
To quit qemu type: Ctrl-a x.

sleep(easy)

使用system call sleep.函数(在user/user.h中被声明)来完成

/*sleep.c
*/#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"int main(int argc, char *argv[])
{if(argc != 2) {printf("error, usage: <sleep> <sleep_time>\n");exit(1);}int sleep_time = atoi(argv[1]);/* 调用sleep函数 */sleep(sleep_time);exit(0);
}

pingpong(easy)

使用系统调用在一对管道上的两个进程之间“乒乓”一个字节,每个方向一个。父进程应该向子进程发送一个字节;子进程应打印“<pid>:received ping”,其中<pid>是其进程ID,将管道上的字节写入父进程,然后退出;父进程应该读取子进程的字节,打印“<pid>:received-pong”,然后退出。

/*pingpong.c
*/#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"int main(int argc, char *argv[])
{if(argc != 1) {printf("error, usage: <pingpong>\n");exit(1);}int pid;/* create pipe */int fd[2];if(pipe(fd) == -1) exit(1);pid = fork();char buf[10];if(pid == 0) /* child process */{int pid_this = getpid();char *str = "pong";read(fd[0], buf, sizeof(buf)); // 阻塞,等待父进程发送printf("%d: received %s\n", pid_this, buf);write(fd[1], str, strlen(str));close(fd[1]);}else{ /* parent process */int pid_this = getpid();char *str = "ping";write(fd[1], str, strlen(str));close(fd[1]);wait(0); //等待子进程退出,再去读取read(fd[0], buf, sizeof(buf));printf("%d: received %s\n", pid_this, buf);}exit(0);
}

primes (moderate)/(hard)

使用管道通信实现素数筛,求解35以内的素数。

此算法的核心如下:对于任何一级流水线而言,到达当前流水线级的最小数字一定是一个素数,因为在处理之前比它更小的数字时它没有被筛掉,在当前流水线下它也需要作为一个基数去筛掉它在现存数字中的所有倍数,将所有剩下来的数字送入下一级流水线,直到本级流水线只剩下一个数字时,整个筛法结束。

/*a concurrent version of prime sieve 并发版本的素数筛primes.c
*/#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"static const int N = 35;int main(int argc, char *argv[])
{if(argc != 1) {printf("error, usage: <primes>\n");exit(1);}int left_fd[2];int right_fd[2];pipe(left_fd);int num = 2;for(num = 2; num <= N; num++) write(left_fd[1], &num, sizeof(num));while(1){   if(fork()) {close(left_fd[1]); // 必须关闭父进程的写端close(left_fd[0]);wait(0);exit(0);}else {close(left_fd[1]); // 注意这里,必须关闭子进程的写端,当管道的2个写端都被关闭,read不会发生阻塞,没有数据直接返回pipe(right_fd);int x = -1, base = -1, cnt = 0;while(read(left_fd[0], &x, sizeof(num))){ // 子进程循环读入cnt++;if(base == -1){base = x; // 第一个数必定是素数printf("prime %d\n", base);}else{if((x % base) != 0){ // 晒不掉的送入下一层write(right_fd[1], &x, sizeof(num)); }}// printf("%d ", x);}if(cnt == 1) exit(0);// 这一层与子进程之间的管道是下一层中与父进程之间的管道!left_fd[0] = right_fd[0];left_fd[1] = right_fd[1];}}
}

在这里插入图片描述

find (moderate)

它可以在指定的目录下寻找指定名称的文件并打印出来,在编写代码之前可以从ls.c例程中学习如何读取目录信息,当深入到嵌套的文件夹中寻找时,应该使用递归写法。

文件信息结构体:

// 文件信息结构体
// 其中type表明了文件的类型是:文件、目录还是设备
#define T_DIR     1   // Directory
#define T_FILE    2   // File
#define T_DEVICE  3   // Devicestruct stat {int dev;     // File system's disk deviceuint ino;    // Inode numbershort type;  // Type of fileshort nlink; // Number of links to fileuint64 size; // Size of file in bytes
};

目录结构体:

// Directory is a file containing a sequence of dirent structures.
// 所谓目录,就是一系列dirent结构组成的顺序序列
#define DIRSIZ 14struct dirent {ushort inum;char name[DIRSIZ];
};
/*find.c
*/#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"// 递归查找
void find(char *path, char *name)
{int fd;//关键在下面这两个结构体里面struct stat st; // 获取某个文件的状态struct dirent de; //获取目录下的所有项if((fd = open(path, 0)) < 0) {printf("cannot open %s\n", path);exit(1);}if(fstat(fd, &st) < 0){printf("cannot stat %s\n", path);close(fd);exit(1);}char buf[256]; // 这个数组不能开太大char *p;if(st.type == T_DIR){if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){ // 防止路径太长printf("ls: path too long\n");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;// 根据前面的path,buf,p组合成当前项的绝对路径,获取其属性if(stat(buf, &st) < 0){printf("ls: cannot stat %s\n", buf);continue;}if(st.type == T_FILE) { //当前项是文件,则判断if(strcmp(de.name, name) == 0) printf("%s\n", buf);}else{// 当前项还是目录,则递归查找if(strcmp(de.name, ".") && strcmp(de.name, "..")) // 防止一直递归{find(buf, name);}}}}
}int main(int argc, char *argv[])
{if(argc != 3){printf("error, usage:<find> <path> <name>\n");exit(1);}// read directorieschar path[512], name[512];memcpy(path, argv[1], strlen(argv[1]));memcpy(name, argv[2], strlen(argv[2]));// printf("debug: path = %s\n",path);// printf("debug: name = %s\n",name);// 调用函数findfind(path, name);exit(0);
}

xargs (moderate)

xargs(extensive arguments)是Linux系统中的一个很重要的命令,它一般通过管道来和其他命令一起调用,来将额外的参数传递给命令,这个小问题就是实现自己版本的xargs命令。初次理解xargs命令时还是有点费解的,指导书中的一个例子如下:

$ echo hello too | xargs echo byebye hello too
$

要理解这个例子就将echo hello too | xargs看作一个整体,它本质上是将hello too传递给了xargs,然后经过xagrs的逻辑处理,就会将这些额外传入的参数交给后面的echo命令。我们的任务就是实现这里所谓的xargs的处理逻辑

/*xargs.c
*/
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/param.h"char *g_argv[MAXARG];int main(int argc, char *argv[])
{if(argc < 2) {printf("error, usage:<xargs> <program>\n");exit(1);}if(argc >= MAXARG) {printf("too much argv\n");exit(1);}char c;char buf[32];int i = 0, cnt = 0;for(; cnt < argc - 1; cnt++) { g_argv[cnt] = (char*)malloc(sizeof buf); // 要先分配内存,野指针的解引用是未定义的结果// g_argv[cnt] = 0;// strcpy会对时针进行解引用,然后拷贝g_argv[cnt] = strcpy(g_argv[cnt], argv[cnt + 1]);        }while(read(0, &c, sizeof(c))) // 以字符形式读取完毕{cnt = argc - 1;if(c == '\n' || c == ' '){buf[i] = '\0'; // 结束符// printf("read: %s\n", buf);g_argv[cnt] = (char*)malloc(sizeof buf); // 分配内存g_argv[cnt] = strcpy(g_argv[cnt], buf);cnt++;i = 0;if(c == '\n') // 说明读完一行命令了,要让子进程去执行{   // 此时已经读取完标准输入的argv的if(cnt + (argc - 2) >= MAXARG - 1){printf("too much argv\n");exit(1);}g_argv[cnt] = 0; // 最后一个命令必须为结束符if(fork()){   // 父进程等待子进程结束,等待完处理下一条命令wait(0);}else{ // 子进程exec(argv[1], g_argv);exit(0);}}}else {buf[i++] = c; // 不是空格也不是换行符,那就读取字符}}exit(0);}

调试方式

首先make qemu-gdb CPUS=1,启动gdb-server

然后在另一个终端中(启动gdb客户端)使用gdb-multiarch -q kernel/kernel(kernel/kernel表示要gdb的程序)

进入gdb后

  • b:设置断点
  • c:运行
  • n:单步运行
  • s:进入函数内部

使用gdb的layout split模式可以看到gdb要执行的下一条指令是什么,断点具体在什么位置

提交

创建time.txt,写入耗时

make grade

结果:

$ make qemu-gdb
sleep, no arguments: OK (2.8s) 
== Test sleep, returns == 
$ make qemu-gdb
sleep, returns: OK (0.4s) 
== Test sleep, makes syscall == 
$ make qemu-gdb
sleep, makes syscall: OK (1.0s) 
== Test pingpong == 
$ make qemu-gdb
pingpong: OK (1.0s) 
== Test primes == 
$ make qemu-gdb
primes: OK (1.1s) 
== Test find, in current directory == 
$ make qemu-gdb
find, in current directory: OK (1.0s) 
== Test find, recursive == 
$ make qemu-gdb
find, recursive: OK (1.1s) 
== Test xargs == 
$ make qemu-gdb
xargs: OK (1.1s) 
== Test time == 
time: OK 
Score: 100/100

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/239330.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络——应用层(3)

计算机网络——应用层&#xff08;3&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 点对点&#xff08;P2P&#xff09;P2P网络一般用途优点缺点总结 套接字编程基本步骤UDP套接字TCP套接字基本步骤 二者对比 小程一言 我的计算机网络专栏&#xff0c;是自…

基于SSM的高校班级同学录网站的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

maven导入无法拉取所需依赖

maven导入无法拉取所需依赖 1.原因2.解决搞定收工&#xff01; 1.原因 公司使用的是gradle&#xff0c;配置的私有云&#xff0c;maven里面配置私有云完全使用不了&#xff0c;无论配置国内还是国外的&#xff0c;导入的项目报错拉不到jar包。 <mirror><id>mirro…

倒计时1天|解锁「PolarDB开发者大会」正确打开方式

1月17日 9:30-16:30 北京嘉瑞文化中心 PolarDB开发者大会 明天就要和大家就见面啦&#xff5e; 大会参会指南现已出炉 各位开发者们&#xff0c;请查收~ &#x1f447;&#x1f447;&#x1f447; 点击 大会主页 or 扫描上方二维码 一键抵达大会官网&#x1f447; 查看…

微服务接口工具Swagger2

##1、什么是Swagger? # 官网 https://swagger.io/核心功能 生成接口说明文档生成接口测试工具 2、SpringBoot集成Swagger2 1&#xff09;、添加依赖 <!-- swagger2 --><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --><depen…

数据绑定,defineProperty,v-on,事件处理

目录​​​​​​​ v-bind单向数据绑定 defineProperty 是v-on的简写 事件处理 v-bind单向数据绑定 从name绑定到v-bind到value单向数据绑定&#xff1a; <input type"text" :value"name"> <input type "text" v-model"na…

【GCC】6 接收端实现:周期构造RTCP反馈包

基于m98代码。GCC涉及的代码,可能位于:webrtc/modules/remote_bitrate_estimator webrtc/modules/congestion_controller webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.cc webrtc 之 RemoteEstimatorProxy 对 remote_bitrate_estimator 的 RemoteEstimato…

线性表的应用 | 线性表的合并

线性表的合并 #include <iostream> using namespace std;#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2typedef int Status;// 定义单链表 typedef struct LNode {int data;struct LNode *next; }LNode, *…

网络文件共享服务

一.存储类型 直连式存储&#xff1a;Direct-Attached Storage&#xff0c;简称DAS 存储区域网络&#xff1a;Storage Area Network&#xff0c;简称SAN&#xff08;可以使用空间&#xff0c;管理也是你来管理&#xff09; 网络附加存储&#xff1a;Network-Attached Storage&…

代码随想录 Leetcode18. 四数之和

题目&#xff1a; 代码&#xff08;首刷看解析 2024年1月15日&#xff09;&#xff1a; class Solution { public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> result;sort(nums.begin(), nums.end(…

mac上部署单体hbase

1. 简介 HBase 是一个开源的、分布式的、版本化的典型非关系型数据库。它是 Google BigTable 的开源实现&#xff0c;并且是 Apache 基金会的 Hadoop 项目的一部分1。HBase 在 Hadoop Distributed File System (HDFS) 上运行&#xff0c;作为一个列式存储非关系数据库管理系统…

响应式编程初探-自定义实现Reactive Streams规范

最近在学响应式编程&#xff0c;这里先记录下&#xff0c;响应式编程的一些基础内容 1.名词解释 Reactive Streams、Reactor、WebFlux以及响应式编程之间存在密切的关系&#xff0c;它们共同构成了在Java生态系统中处理异步和响应式编程的一系列工具和框架。 Reactive Streams…

查看Linux系统内存、CPU、磁盘使用率和详细信息

一、查看内存占用 1、free # free -m 以MB为单位显示内存使用情况 [rootlocalhost ~]# free -mtotal used free shared buff/cache available Mem: 11852 1250 8668 410 1934 9873 Swap: 601…

【Kotlin】协程的字节码原理

前言 协程是Koltin语言最重要的特性之一&#xff0c;也是最难理解的特性。网上关于kotlin协程的描述也是五花八门&#xff0c;有人说它是轻量级线程&#xff0c;有人说它是无阻塞式挂起&#xff0c;有人说它是一个异步框架等等&#xff0c;众说纷芸。甚至还有人出了书籍专门介…

Linux用户提权

新建用户 用root账户修改文件&#xff0c;添加信任用户 使用sudo提权&#xff0c;可以使用 **root删除新建账户**

各种版本对应关系:SpringCloudAlibaba——SpringCloud——SpringBoot——SpringFramework——JDK

SpringCloudAlibaba——SpringCloud——SpringBoot——SpringFramework——JDK 一般情况&#xff0c;在https://github.com/项目/wiki目录下有发布信息及对应的要求其他依赖的版本信息SpringCloudAlibaba——SpringCloud——SpringBootSpringBoot和SpringFramework的版本对应关…

Web3的应用发展及其影响

Web3&#xff0c;又被称为去中心化Web&#xff0c;是互联网发展的一个阶段&#xff0c;其核心特点是数据的去中心化和用户自主权。近年来&#xff0c;随着区块链技术的不断成熟&#xff0c;Web3的应用也得到了广泛的关注和发展。在这篇文章中&#xff0c;我们将深入探讨Web3目前…

vuex的初步使用-1

1. 介绍 Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 简单讲&#xff1a;Vuex 就是一个插件&#xff0c;可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。相对于一个仓库&#xff1a;存放组件共享的数据。 2. 安装 vuex 安装vuex与vue-router类似&…

LabVIEW模拟荧光显微管滑动实验

LabVIEW模拟荧光显微管滑动实验 在现代生物医学研究中&#xff0c;对微观生物过程的精准模拟和观察至关重要。本案例展示了如何利用LabVIEW软件和专业硬件平台&#xff0c;创新地模拟荧光显微管在滑动实验中的动态行为&#xff0c;这一过程不仅提升了实验效率&#xff0c;还为…

Jenkins基础篇--添加用户和用户权限设置

添加用户 点击系统管理&#xff0c;点击管理用户&#xff0c;然后点击创建用户&#xff08;Create User&#xff09; 用户权限管理 点击系统管理&#xff0c;点击全局安全配置&#xff0c;找到授权策略&#xff0c;选择安全矩阵&#xff0c;配置好用户权限后&#xff0c;点击…