操作系统入门系列-MIT6.828(操作系统工程)学习笔记(三)---- xv6初探与实验一(Lab: Xv6 and Unix utilities)

系列文章目录

操作系统入门系列-MIT6.S081(操作系统)学习笔记(一)---- 操作系统介绍与接口示例
操作系统入门系列-MIT6.828(操作系统工程)学习笔记(二)----课程实验环境搭建(wsl2+ubuntu+quem+xv6)
操作系统入门系列-MIT6.828(操作系统工程)学习笔记(三)---- xv6初探与实验一(Lab: Xv6 and Unix utilities)


文章目录

  • 系列文章目录
  • 前言
  • 一、xv6文档第一章
    • 1. 引论
  • 二、实验一
    • 1.启动xv6
    • 2.实现休眠函数
    • 3.实现父子进程pingpong打印
    • 4.使用pipeline实现质数检测
    • 5.实现find函数(文件查找)
    • 6.实现xargs函数
  • 总结


前言

MIT 6.828课程资料与进度计划表
完成第一节课的学习后,按照课程的计划进度表,应当阅读xv6文档的第一章节,以及完成实验1。
本文主要内容就是对xv6文档(2023年版)和实验(2023年版)的讲解
xv6英文文档—2023
xv6中文文档—2013
xv6实验1原文


一、xv6文档第一章

1. 引论

xv6操作系统提供 Unix 操作系统中的基本接口(由 Ken Thompson 和 Dennis Ritchie 引入),同时模仿 Unix 的内部设计,包括 BSD,Linux,Mac OS X,Solaris (甚至 Microsoft Windows 在某种程度上)都有类似 Unix 的接口,理解 xv6 是理解这些操作系统的一个良好起点。
首先需要对操作系统有一个系统结构的大致概念,如下图:
在这里插入图片描述
如图所示,操作系统的核心就是kernel。kernel起到了桥梁的作用,连接各种应用程序和底层硬件资源。从软件编程者的角度来看,程序员就是使用各种kernel提供的系统调用函数,来实现各种各样的功能。xv6的系统调用函数如下图所示:
在这里插入图片描述
后面的实验就是需要调用这些系统调用函数来实现相应的功能,比如在Linux里面常用的find、xargs等命令的简易版。
在之前的文章中已经将第一章的部分进行了讲解,详情见:
操作系统入门系列-MIT6.S081(操作系统)学习笔记(一)---- 操作系统介绍与接口示例

二、实验一

1.启动xv6

详见xv6环境的配置和启动
操作系统入门系列-MIT6.828(操作系统工程)学习笔记(二)----课程实验环境搭建(wsl2+ubuntu+quem+xv6)
(1)实验系统目录:
整个实验代码的文件目录如下,我们需要关注:

1.绿色的”grade-lab-util“可执行文件,它是测试机,用来测试你的实验代码正确性。
2.kernel文件夹,是xv6的kernel代码
3.Makefile是用来编译内核的,需要在这里添加参数,我们写的实验代码才能编译进去
4.user文件夹是我们添加自己实验代码的地方,也就是用户空间	

在这里插入图片描述
(2)Makefile添加文件
在这里插入图片描述
(3)退出xv6
使用”ctrl+a“,后按x退出
(4)测试机打分
需要在lab目录中添加time.txt文件,里面写一个整数,代表你的实验花了多少小时。
在这里插入图片描述

2.实现休眠函数

(1)原题如下:
在这里插入图片描述
(2)大致内容为:
调用“系统调用函数——sleep()”(一次sleep()系统暂停一个tick),实现输入数字,系统暂停该数字次数的ticks。
参数错误时,要有错误打印
(3)代码如下:

// 参考echo.c、grep.c、rm.c的头文件引用
#include "kernel/types.h"//声明数据类型
#include "kernel/stat.h"//声明文件数据结构
#include "kernel/fcntl.h"//open函数的模式参数申明
#include "user/user.h"//声明各种系统调用函数、以及有用的库函数int main(int argc, char *argv[])
{int number;//参数数量不对,打印错误信息//参数还有其他错误情况,此处仅考虑数量问题if(argc <= 1){fprintf(2, "usage: sleep number\n");exit(1);}number = atoi(argv[1]);//字符串转整数sleep(number);//系统调用exit(0);
}

(4)结果如下:
使用官方提供的测试机程序,在lab目录下面运行"./grade-lab-util + 文件名"

./grade-lab-util sleep

测试机自主进行测试,如下图:
在这里插入图片描述
(5)总结:
在做实验之前我们需要知道有哪些函数我们是可以调用的,可以查看文件:“user/user.h”

struct stat;// system calls
int fork(void);
int exit(int) __attribute__((noreturn));
int wait(int*);
int pipe(int*);
int write(int, const void*, int);
int read(int, void*, int);
int close(int);
int kill(int);
int exec(const char*, char**);
int open(const char*, int);
int mknod(const char*, short, short);
int unlink(const char*);
int fstat(int fd, struct stat*);
int link(const char*, const char*);
int mkdir(const char*);
int chdir(const char*);
int dup(int);
int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);// ulib.c
int stat(const char*, struct stat*);
char* strcpy(char*, const char*);
void *memmove(void*, const void*, int);
char* strchr(const char*, char c);
int strcmp(const char*, const char*);
void fprintf(int, const char*, ...);
void printf(const char*, ...);
char* gets(char*, int max);
uint strlen(const char*);
void* memset(void*, int, uint);
void* malloc(uint);
void free(void*);
int atoi(const char*);
int memcmp(const void *, const void *, uint);
void *memcpy(void *, const void *, uint);

3.实现父子进程pingpong打印

(1)原题如下:
在这里插入图片描述
(2)大致内容为:
实现过程:父进程向子进程发送ping,子进程打印该信息,后子进程向父进程发送pong,父进程再打印该信息
实现结果为:
在这里插入图片描述

(3)代码如下:
分为单管道实现和双管道实现
单管道实现:

#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fcntl.h"
#include "user/user.h"int main(int argc, char *argv[])
{int p[2];char buf[512];//用来接收信息的bufferpipe(p);//父 <=======> 子//子进程执行if,父进程执行elseif(fork() == 0){read(p[0], buf, sizeof(buf));//阻塞,直到父进程写入管道p内容,后读取父进程的信息fprintf(1,"%d: received %s\n", getpid(), buf);//打印父进程的信息write(p[1], "pong", 5);//使用p的写通道向父进程发送信息close(p[0]);//关闭读通道close(p[1]);//关闭写通道exit(0);//子进程退出}else{write(p[1], "ping", 5);//父进程通过p的写通道向子进程发送信息wait((int *)0);//等待子进程结束read(p[0], buf, sizeof(buf));//读取p管道中子进程的信息fprintf(1,"%d: received %s\n", getpid(), buf);//打印子进程的信息close(p[0]);//关闭读通道close(p[1]);//关闭写通道}exit(0);
}

双管道实现:

#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fcntl.h"
#include "user/user.h"int main(int argc, char *argv[])
{int p[2];int p2[2];char buf[512];//用来接收信息的buffer//向内核申请两个管道pipe(p);//父进程写,子进程读:父 ——————> 子pipe(p2);//子进程写,父进程读:子 ——————> 父//子进程执行if,父进程执行elseif(fork() == 0){close(p[1]);//关闭p的写通道,以便于父进程写完可以直接读取read(p[0], buf, sizeof(buf));//阻塞,直到父进程写入管道p内容,后读取父进程的信息fprintf(1,"%d: received %s\n", getpid(), buf);//打印父进程的信息close(p[0]);//关闭p的读通道write(p2[1], "pong", 5);//使用p2的写通道向父进程发送信息close(p2[1]);//写完关闭写通道close(p2[0]);//关闭p2的读通道exit(0);//子进程退出}else{write(p[1], "ping", 5);//父进程通过p的写通道向子进程发送信息close(p[1]);//写完关闭写通道close(p2[1]);//关闭p2的写通道,以便于子进程写完可以直接读取read(p2[0], buf, sizeof(buf));//阻塞,直到子进程写入管道p2内容,读取子进程的信息fprintf(1,"%d: received %s\n", getpid(), buf);//打印子进程的信息close(p[0]);//关闭p的读通道close(p2[0]);//关闭p2的读通道}exit(0);//结束程序
}

(4)结果如下:
在这里插入图片描述
(5)总结:

4.使用pipeline实现质数检测

(1)原题如下:
在这里插入图片描述
(2)大致内容为:
使用pipeline+多进程来检测35以内的质数检测
这个过程比较难想,但是在纸上推演一下流程就懂了,参考文献如下:Bell Labs and CSP Threads

参考伪代码:
在这里插入图片描述
参考图:
在这里插入图片描述
(3)代码如下:

#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fcntl.h"
#include "user/user.h"void child(int * p)
{int p1[2];char num[35];int prime;int i;int ret;int number;pipe(p1);close(p[1]);number = 0;for(i=0;i<35;i++){ret = read(p[0], num+i, 1);if(ret == 0){break;}number++;}if(number == 0){exit(0);}prime = num[0];printf("prime %d\n", prime);close(p[0]);if(fork() == 0){child(p1);}else{close(p1[0]);for(i=1;i<number;i++){if((num[i]%prime)!=0){write(p1[1], num+i, 1);}}close(p1[1]);wait((int *)0);}exit(0);
}int main()
{int prime = 2;int p[2];int i;pipe(p);if(fork() == 0){child(p);}else{close(p[0]);printf("prime %d\n", prime);for(i=3;i<=35;i++){if((i%prime)!=0){write(p[1], &i, 1);}}close(p[1]);wait((int *)0);}exit(0);
}

(4)结果如下:
在这里插入图片描述
在这里插入图片描述
(5)总结:
核心是算法题,载体是进程树之间使用pipeline进行读写控制

5.实现find函数(文件查找)

(1)原题如下:
在这里插入图片描述
(2)大致内容为:
实现目录下搜索文件的功能,要求能够找到该文件夹目录下以及其子目录下的指定文件名,输出所有满足文件的路径。(不要求实现正则表达式)(!!!记得规避".“与”…"子文件)(如何访问文件夹可以参考文件ls.c的实现)

  "  .  "  表示当前目录"  ..  "  表示当前目录的上一级目录。"  ./  "  表示当前目录下的某个文件或文件夹,视后面跟着的名字而定"  ../  "   表示当前目录上一级目录的文件或文件夹,视后面跟着的名字而定。

在这里插入图片描述
(3)代码如下:

#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fcntl.h"
#include "kernel/fs.h"
#include "user/user.h"char* fmtname(char *path)
{char *p;// Find first character after last slash.for(p=path+strlen(path); p >= path && *p != '/'; p--);p++;return p;
}int find(char *name, char *p)
{int fd;int path=0;char buf[512];struct dirent de;struct stat st;fd = open(p, O_RDONLY);if(fd < 0){fprintf(2, "fd: can not open %s\n");exit(1);}strcpy(buf, p);p = buf+strlen(buf);*p++ = '/';// printf("%d  %s\n", fd, buf);while(read(fd, &de, sizeof(de)) == sizeof(de)){if(de.inum == 0){continue;}memmove(p, de.name, DIRSIZ);p[DIRSIZ] = 0;// printf("%s\n", p);if(stat(buf, &st) < 0){printf("ls: cannot stat %s\n", buf);continue;}// printf("%s %s %d\n", buf, fmtname(buf), st.type);// printf("%d %d %d\n", strcmp(fmtname(buf), name), strcmp(fmtname(buf), "."), strcmp(".", "."));if (st.type == T_FILE && (strcmp(fmtname(buf), name) == 0)){printf("%s\n", buf);path = 1;} if (st.type == T_DIR && (strcmp(fmtname(buf), ".") != 0) && (strcmp(fmtname(buf), "..") != 0)){path = find(name, buf);}   }return path;
}int main(int argc, char *argv[])
{int path;if(argc < 3){fprintf(2, "fd: find [dir] [filename]\n");exit(1);}path = find(argv[2], argv[1]);if(path == 0){fprintf(1, "can not find such file\n");}exit(0);
}

(4)结果如下:
在这里插入图片描述
(5)总结:
核心知识点是xv6系统下的文件结构体与文件夹结构体,使用递归方法进行实现。

6.实现xargs函数

(1)原题如下:
在这里插入图片描述
(2)大致内容为:
实现xargs命令,xargs命令很难简单理解,建议先查一下命令的用法。
xargs 命令教程
(3)代码如下:

#include "kernel/types.h"
#include "kernel/stat.h"
#include "kernel/fcntl.h"
#include "user/user.h"
#include "kernel/param.h"int getcmd(char *buf, char**arg, int arg_num)
{int i;int j;j = 0;arg[arg_num] = (char *)malloc(30 * sizeof(char));for(i=0; i<512; i++){if((buf[i] == ' ') || (buf[i] == 10) || (buf[i] == '\0') || (buf[i] == '\n')){// printf("%c %d\n", buf[i], buf[i]);arg_num++;if(buf[i] == 10){// printf("argmun: %d\n", arg_num);return arg_num;}if(buf[i] == '\0'){// printf("argmun: %d\n", arg_num);return arg_num;}arg[arg_num] = (char *)malloc(30 * sizeof(char));// printf("111\n");// printf("%s %p kkk\n", arg[arg_num], arg[arg_num]);j = 0;}else{// printf("%d %d %c %d\n", j, i, buf[i], arg[arg_num][j]);arg[arg_num][j] = buf[i];// printf("%d %c \n", j, arg[arg_num][j]);j++;}}return arg_num;
}int main(int argc, char *argv[])
{char buf[512];int num = 0;int ret;int cmd = 0;char *arg[MAXARG];int arg_num;arg_num = argc - 1;int i = 0;for(i=0; i<arg_num; i++){arg[i] = argv[i+1];}if(argc < 2){fprintf(2, "xarg: xarg [process] [args...]\n");exit(1);}int j = 0;while(1){ret = read(0, buf+j, 1);if(ret != 1){break;}else if(buf[j] == '\n'){// printf("read number is : %d\n%s\n", num, buf);j = 0;num = 0;cmd = getcmd(buf, arg, arg_num);// printf("\n\n%d %d\n", cmd, arg_num);// printf("%s\n%s\n%s\n%s\n", arg[0], arg[1], arg[2], arg[3]);if(cmd == arg_num){printf("%d %d\n", cmd, arg_num);printf("no content of stdin\n");}else{if(fork() == 0){exec(argv[1], arg);fprintf(2, "exec failed\n");exit(1);}else{wait((int *)0);}}}else{j++;num++;}}for(i=0; i<cmd; i++){free(arg[i]);}exit(0);
}

(4)结果如下:
在这里插入图片描述
(5)总结:
在实现字符串的单词分割的时候,对于指针的操作出现问题。
char **arg的arg[]元素应该动态分配空间,而不是讲temp数组的指针头直接赋值。


总结

课程每年可能有变化,本文按照最新的2023计划表进行学习

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

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

相关文章

RocketMQ相关知识知多少

一、RocketMQ的定义 官网网址&#xff1a;领域模型概述 | RocketMQ Apache RocketMQ 自诞生以来&#xff0c;因其架构简单、业务功能丰富、具备极强可扩展性等特点被众多企业开发者以及云厂商广泛采用。历经十余年的大规模场景打磨&#xff0c;RocketMQ 已经成为业内共识的金…

Flink的简单学习二

一 Flink的核心组件 1.1 client 1.将数据流程图DataFlow发送给JobManager。 1.2 JobManager 1.收集client的DataFlow图&#xff0c;将图分解成一个个的task任务&#xff0c;并返回状态更新数据给client 2.JobManager负责作业调度&#xff0c;收集TaskManager的Heartbeat和…

三、基于图像分类预训练编码及图神经网络的预测模型 【框图+源码】

背景&#xff1a; 抽时间补充&#xff0c;先挖个坑。 一、模型结构 二、源码

美团一面:什么是CAS?有什么优缺点?我说你说的是AtomicInteger吗?

引言 传统的并发控制手段&#xff0c;如使用synchronized关键字或者ReentrantLock等互斥锁机制&#xff0c;虽然能够有效防止资源的竞争冲突&#xff0c;但也可能带来额外的性能开销&#xff0c;如上下文切换、锁竞争导致的线程阻塞等。而此时就出现了一种乐观锁的策略&#x…

企业数字化转型的测度难题:基于大语言模型的新方法与新发现

《经济研究》新文章《企业数字化转型的测度难题&#xff1a;基于大语言模型的新方法与新发现》运用机器学习和大语言模型构造一套新的企业数字化转型指标。理论分析和数据交叉验证均表明&#xff0c;构建的指标相对已有方法更准确&#xff1a; 1.第一步&#xff1a;选择“管理…

17.Redis之主从复制

1.主从复制是怎么回事&#xff1f; 分布式系统, 涉及到一个非常关键的问题: 单点问题 单点问题&#xff1a;如果某个服务器程序, 只有一个节点(只搞一个物理服务器, 来部署这个服务器程序) 1.可用性问题,如果这个机器挂了,意味着服务就中断了~ 2.性能/支持的并发量也是比较有限…

【HarmonyOS】鸿蒙系统中应用权限等级介绍、定义、申请授权讲解

【HarmonyOS】鸿蒙系统中应用权限等级介绍、定义、申请授权讲解 针对权限等级&#xff0c;相对于主体来说&#xff0c;会有不同的细分概念。 一、权限APL等级&#xff1a; 首先在鸿蒙系统中&#xff0c;对于权限本身&#xff0c;分为三个等级&#xff1a;normal&#xff0c;s…

SQL面试问题集

目录 Q.左连接和右连接的区别 Q.union 和 union all的区别 1、取结果的交集 2、获取结果后的操作 Q.熟悉开窗函数吗&#xff1f;讲一下row_number和dense_rank的区别。 Q.hive行转列怎么操作的 Q.要求手写的题主要考了聚合函数和窗口函数&#xff0c;row_number()&#…

同一个tomcat不同端口运行不同项目

第一步&#xff1a;修改 server.xml 文件 修改 tomcat 安装目录下 conf/server.xml 文件&#xff0c;需要几个端口就添加几个 Service 节点。 配置 2 个端口&#xff1a;9131 和 9133&#xff0c;于是增加两个 Service 节点。 每个 Service 节点的 name 属性值要设置不同的值…

【MATLAB】雷达信号处理程序源码 雷达系统仿真代码 matlab SAR

【MATLAB】雷达信号处理程序源码 雷达系统仿真代码 matlab SAR 包含以下所有源码,内容如下&#xff1a;&#xff1a; 1、 MATGPR R3探地雷达数据处理 MATLAB 程序 2、 python 雷达图像识别 3、 SAR 雷达回波仿真 matlab 4、 SAR 雷达影像处理源码 5、 STFT 处理 IPIX 雷达…

数据分析常用模型合集(三)同期群、逻辑树、假设检验等

前面两篇文章&#xff0c;我们将比较大、较为系统的分析方法作了一个介绍&#xff0c;本文是最后一篇&#xff0c;将剩余的一些讲一讲。 数据分析常用模型合集&#xff08;二&#xff09;RARRA模型、RFM模型-CSDN博客 剩下的一些模型&#xff0c;其实不应叫做模型&#xff0c;…

qt+ffmpeg 实现音视频播放(四)之音视频同步

在处理音视频数据时&#xff0c;解码音频的数据往往会比解码视频的数据比较慢&#xff0c;所以我们在播放音视频时&#xff0c;音频和视频的数据会出现渐渐对不上的情况。尤其在播放时间越长的时候&#xff0c;这种对不上的现象越明显。 为了解决这一问题&#xff0c;人们想出…

在windows操作系统上安装MariaDB

最近收到关于数据库在哪里看的评论&#xff0c;所以就一不做二不休&#xff0c;把安装数据库的步骤写一篇文章吧。 这篇文章介绍如何在windows上完成MariaDB-10.6.5版本的安装&#xff0c;对应MySQL-8.x版本。 第一步&#xff1a;下载安装包 通过以下网盘链接下载MariaDB-10.6…

国产信创CPU之飞腾CPU剖析

CPU&#xff1a;信创根基&#xff0c;国之重器 国产CPU已形成自主架构、x86、ARM三大阵营。自主阵营中&#xff0c;龙芯、申威分别基于MIPS和Alpha推出loong ISA和SW-64。ARM阵营以鲲鹏、飞腾为代表&#xff0c;利用ARM IP授权开发处理器。x86阵营由海光、兆芯等主导&#xff…

【Linux】操作系统中的文件系统管理:磁盘结构、逻辑存储与文件访问机制

文章目录 前言&#xff1a;1. 磁盘机械结构2. 磁盘物理结构3. 磁盘的逻辑存储3. 1. 文件名呢&#xff1f;3.2 对文件的增删查改与 路径3.3. 文件 4. 软硬链接4.1. 操作观察现象4.2. 软硬链接的原理4.3. 软硬链接的应用场景 总结 前言&#xff1a; 在现代操作系统中&#xff0c…

基于Springboot+vue实现的汽车服务管理系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

45.自定义线程池(三)-拒绝策略

拒绝策略采用函数式接口参数传入&#xff0c;策略模式 FunctionalInterface public interface RejectPolicy<T> {void reject(BlockingQueue<T> queue, T task); } package com.xkj.thread.pool;import com.aspose.words.Run; import lombok.extern.slf4j.Slf4j;…

SaaS 电商设计 (十一) 那些高并发电商系统的限流方案设计

目录 一.什么是限流二.怎么做限流呢2.1 有哪些常见的系统限流算法2.1.1 固定窗口2.1.1 滑动窗口2.1.2 令牌桶2.1.3 漏桶算法 2.2 常见的限流方式2.2.1 单机限流&集群限流2.2.2 前置限流&后置限流 2.3 实际落地是怎么做的2.3.1 流量链路2.3.2 各链路限流2.3.2.1 网关层2…

重学java 56. Map集合

我们要拥有一定成功的信念 —— 24.6.3 一、双列集合的集合框架 HashMap 1.特点: a.key唯一,value可重复 b.无序 c.无索引 d.线程不安全 e.可以存null键,null值 2.数据结构:哈希表 LinkedHashMap&#xff08;继承HashMap&#xff09; 1.特点: a.key唯一,value可重复 b.有序 c.无…

矩阵连乘问题

#include<iostream> using namespace std; #define N 7 void MatrixChain(int p[N],int n,int m[N][N],int s[N][N]) {for(int i1;i<n;i)m[i][i]0;for(int r2;r<n;r)//有多少个相乘(规模){for(int i1;i<n-r1;i){int jir-1;m[i][j]m[i][i]m[i1][j]p[i]*p[i1]*p[j…