123.Mit6.S081-实验1-Xv6 and Unix utilities

今天我们来进行Mit6.S081实验一的内容。

实验任务

一、启动xv6(难度:Easy)

获取实验室的xv6源代码并切换到util分支。

$ 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'

1.构建并运行xv6

make qemu

2.测试xv6

        这些是mkfs在初始文件系统中包含的文件;大多数是可以运行的程序。刚刚跑了其中的:ls、cat

3.退出qemu

查看xv6中的进程:Ctrl+p(xv6没有实现ps程序),
退出qemu启动的xv6:Ctrl+a x

4.分析

        xv6通过qemu启动完成后,启动了shell进程。通过shell,启动子进程ls、cat,显示了xv6目录下的文件。

参考:Lab1: Xv6 and Unix utilities · 6.S081 All-In-One (dgs.zone)

 二、sleep(难度:Easy)

1.需求

        实现xv6的UNIX程序sleep:您的sleep应该暂停到用户指定的计时数。一个滴答(tick)是由xv6内核定义的时间概念,即来自定时器芯片的两个中断之间的时间。您的解决方案应该在文件user/sleep.c

2.提示

第一章 操作系统接口 · 6.S081 All-In-One (dgs.zone)(参考)

  • 在你开始编码之前,请阅读《book-riscv-rev1》的第一章(上述链接)。

  • 看看其他的一些程序(如/user/echo.c, /user/grep.c, /user/rm.c)查看如何获取传递给程序的命令行参数

  • 如果用户忘记传递参数,sleep应该打印一条错误信息

  • 命令行参数作为字符串传递; 您可以使用atoi将其转换为数字(详见/user/ulib.c

  • 使用系统调用sleep

  • 请参阅kernel/sysproc.c以获取实现sleep系统调用的xv6内核代码(查找sys_sleep),user/user.h提供了sleep的声明以便其他程序调用,用汇编程序编写的user/usys.S可以帮助sleep从用户区跳转到内核区。

  • 确保main函数调用exit()以退出程序。

  • 将你的sleep程序添加到Makefile中的UPROGS中;完成之后,make qemu将编译您的程序,并且您可以从xv6的shell运行它。

参考以下代码(查看如何获取传递给程序的命令行参数)

types.h

typedef unsigned int   uint;
typedef unsigned short ushort;
typedef unsigned char  uchar;typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int  uint32;
typedef unsigned long uint64;typedef uint64 pde_t;/*
这段代码是在 C 语言中使用 typedef 关键字定义了一些新的数据类型:uint:无符号整数,通常是 unsigned int 类型。
ushort:无符号短整数,通常是 unsigned short 类型。
uchar:无符号字符,通常是 unsigned char 类型。
然后定义了一些更具体的无符号整数类型:uint8:8 位无符号整数,通常是 unsigned char 类型。
uint16:16 位无符号整数,通常是 unsigned short 类型。
uint32:32 位无符号整数,通常是 unsigned int 类型。
uint64:64 位无符号整数,通常是 unsigned long 类型。
最后,定义了一个名为 pde_t 的类型,它被定义为 uint64 类型,通常用于表示页表项(Page Directory Entry)中的地址或者数据。
*/

start.h

#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
};/*
这段代码定义了一些常量以及一个结构体 struct stat,用于描述文件系统中文件的状态信息。常量定义:
T_DIR:表示目录类型,其值为 1。
T_FILE:表示文件类型,其值为 2。
T_DEVICE:表示设备类型,其值为 3。
结构体 struct stat 包含以下成员:
int dev:表示文件所在的文件系统的磁盘设备。
uint ino:表示文件的 inode 号码。
short type:表示文件的类型,可以是 T_DIR、T_FILE 或者 T_DEVICE。
short nlink:表示指向该文件的硬链接数目。
uint64 size:表示文件的大小,以字节为单位。
这个结构体用于保存文件的各种属性信息,比如文件类型、大小、所在设备等。在实际的文件系统中,通过这些信息可以对文件进行管理和操作。
*/

user.h

struct stat;
struct rtcdate;// 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(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);/*
这段代码展示了一些结构体和系统调用函数的声明,以及一些在 ulib.c 文件中实现的库函数声明。这些声明通常用于操作系统的实现中,特别是在 Unix/Linux 系统中。struct stat; 和 struct rtcdate;:这些是结构体声明,但是具体的结构体定义并没有在这段代码中给出。这样的声明表明这些结构体在其他地方有定义,可能是在其他文件或者系统头文件中。
系统调用函数声明:
这些函数声明了一些常见的系统调用函数,如 fork、exit、wait、pipe 等,用于操作进程、文件和系统状态等。
每个函数声明描述了函数的参数和返回类型,有些函数使用了 __attribute__((noreturn)) 指示函数不会返回(如 exit)。
ulib.c 文件中的库函数声明:
这些函数声明了一些在 ulib.c 文件中实现的库函数,如字符串操作函数 strcpy、strcmp、内存操作函数 memmove、memset 等,以及输出函数 fprintf、printf 和内存分配函数 malloc、free 等。
这些声明描述了操作系统的核心功能,包括进程管理、文件操作、内存管理等。
*/

echo.c

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"int
main(int argc, char *argv[])
{int i;for(i = 1; i < argc; i++){write(1, argv[i], strlen(argv[i]));if(i + 1 < argc){write(1, " ", 1);} else {write(1, "\n", 1);}}exit(0);
}
/*
#include "kernel/types.h"、#include "kernel/stat.h"、#include "user/user.h":这些是头文件包含语句,用于包含所需的系统头文件,以便在程序中使用相关的函数和数据结构。
main 函数:这是程序的入口函数,它接收命令行参数 argc 和 argv[],其中 argc 表示参数的个数,argv[] 是一个指向参数字符串数组的指针。
for 循环:遍历命令行参数数组 argv[],从索引 1 开始(跳过程序名称本身),将每个参数字符串使用 write 函数写入到标准输出(文件描述符 1)。
write 函数:用于向文件描述符写入数据,第一个参数是文件描述符(1 表示标准输出),第二个参数是要写入的数据,第三个参数是要写入的数据长度。
在循环中,如果不是最后一个参数,则在参数之间插入空格;如果是最后一个参数,则在参数后面插入换行符 \n。
exit(0):正常退出程序,参数 0 表示程序正常结束。
*/

grep.c

// Simple grep.  Only supports ^ . * $ operators.#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"char buf[1024];
int match(char*, char*);void
grep(char *pattern, int fd)
{int n, m;char *p, *q;m = 0;while((n = read(fd, buf+m, sizeof(buf)-m-1)) > 0){m += n;buf[m] = '\0';p = buf;while((q = strchr(p, '\n')) != 0){*q = 0;if(match(pattern, p)){*q = '\n';write(1, p, q+1 - p);}p = q+1;}if(m > 0){m -= p - buf;memmove(buf, p, m);}}
}int
main(int argc, char *argv[])
{int fd, i;char *pattern;if(argc <= 1){fprintf(2, "usage: grep pattern [file ...]\n");exit(1);}pattern = argv[1];if(argc <= 2){grep(pattern, 0);exit(0);}for(i = 2; i < argc; i++){if((fd = open(argv[i], 0)) < 0){printf("grep: cannot open %s\n", argv[i]);exit(1);}grep(pattern, fd);close(fd);}exit(0);
}// Regexp matcher from Kernighan & Pike,
// The Practice of Programming, Chapter 9.int matchhere(char*, char*);
int matchstar(int, char*, char*);int
match(char *re, char *text)
{if(re[0] == '^')return matchhere(re+1, text);do{  // must look at empty stringif(matchhere(re, text))return 1;}while(*text++ != '\0');return 0;
}// matchhere: search for re at beginning of text
int matchhere(char *re, char *text)
{if(re[0] == '\0')return 1;if(re[1] == '*')return matchstar(re[0], re+2, text);if(re[0] == '$' && re[1] == '\0')return *text == '\0';if(*text!='\0' && (re[0]=='.' || re[0]==*text))return matchhere(re+1, text+1);return 0;
}// matchstar: search for c*re at beginning of text
int matchstar(int c, char *re, char *text)
{do{  // a * matches zero or more instancesif(matchhere(re, text))return 1;}while(*text!='\0' && (*text++==c || c=='.'));return 0;
}/*
这段代码实现了一个简单的 grep 命令,可以在文本中搜索指定的模式(pattern)。它支持基本的正则表达式操作符 ^、.、* 和 $。以下是代码中主要部分的解释:grep 函数:
接收一个模式 pattern 和一个文件描述符 fd(如果为 0,则表示从标准输入读取)。
使用 read 函数从文件描述符中读取数据到缓冲区 buf 中。
使用 match 函数匹配模式并输出匹配的行。
main 函数:
解析命令行参数,如果参数个数不符合要求则打印用法信息并退出。
提取模式 pattern 和需要搜索的文件。
对每个文件,打开文件并调用 grep 函数进行搜索,最后关闭文件。
match、matchhere 和 matchstar 函数:
这些函数实现了简单的正则表达式匹配逻辑。
match 函数用于在文本中查找模式。
matchhere 函数用于在文本开头匹配模式。
matchstar 函数用于处理 * 操作符。
这个程序的核心逻辑在于 match 函数和相关的匹配函数,它们用于实现基本的正则表达式匹配功能。
*/

rm.c

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"int
main(int argc, char *argv[])
{int i;if(argc < 2){fprintf(2, "Usage: rm files...\n");exit(1);}for(i = 1; i < argc; i++){if(unlink(argv[i]) < 0){fprintf(2, "rm: %s failed to delete\n", argv[i]);break;}}exit(0);
}/*
这段代码实现了一个简单的 rm(删除文件)命令,可以删除指定的文件。让我们来看一下代码的主要部分:#include "kernel/types.h"、#include "kernel/stat.h"、#include "user/user.h":这些是头文件包含语句,用于包含所需的系统头文件和声明相关的函数和数据结构。
main 函数:这是程序的入口函数,它接收命令行参数 argc 和 argv[],其中 argc 表示参数的个数,argv[] 是一个指向参数字符串数组的指针。
参数检查:程序首先检查参数个数是否符合要求,如果小于 2,则打印用法信息并退出程序。
循环删除文件:程序使用 unlink 函数删除每个指定的文件。如果删除失败(unlink 返回值小于 0),则打印错误信息,并退出循环。
exit:正常退出程序,参数 0 表示程序正常结束。
*/

3.sleep代码(写在user/sleep.c)

#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h" // 必须以这个顺序 include,由于三个头文件有依赖关系int main(int argc, char **argv)
{if (argc < 2){printf("usage: sleep <ticks>\n");exit(0);}sleep(atoi(argv[1]));exit(0);
}/*
代码实现了一个简单的 sleep 命令,用于让当前进程睡眠指定的时钟 tick 数量。以下是代码的一些说明:错误处理: 如果参数个数小于 2,即用户未提供睡眠时间参数,程序会打印用法信息并退出。
参数转换: 通过 atoi 函数将字符串形式的睡眠时间参数转换为整数。
睡眠功能: 使用 sleep 系统调用使当前进程睡眠指定的时钟 tick 数量。
退出码: 程序成功执行后,返回退出码 0,表示正常结束。
*/

4.编译配置

在Makefile下添加配置。

5.测试sleep程序

xv6通过qemu启动完成后,启动了shell进程。通过shell,启动子进程sleep。

 

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

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

相关文章

Go 堆内存分配源码解读

简要介绍 在Go的内存分配中存在几个关键结构&#xff0c;分别是page、mspan、mcache、mcentral、mheap&#xff0c;其中mheap中又包括heapArena&#xff0c;具体这些结构在内存分配中担任什么角色呢&#xff1f; 如下图&#xff0c;可以先看一下整体的结构&#xff1a; mcach…

Linux进程详解二:创建、状态、进程排队

文章目录 进程创建进程状态进程排队 进程创建 pid_t fork(void) 创建一个子进程成功将子进程的pid返回给父进程&#xff0c;0返回给新创建的子进程 fork之后有两个执行分支&#xff08;父和子&#xff09;&#xff0c;fork之后代码共享 bash -> 父 -> 子 创建一个进…

比特币成长的代价

作者&#xff1a;Jeffrey Tucker&#xff0c;作家和总裁。曾就经济、技术、社会哲学和文化等话题广泛发表演讲。编译&#xff1a;秦晋 2017 年之后参与比特币市场的人遇到了与之前的人不同的操作和理想。如今&#xff0c;没有人会太在意之前的事情&#xff0c;说的是 2010-2016…

【全网首发】Mogdb 5.0.6新特性:CM双网卡生产落地方案

在写这篇文章的时候&#xff0c;刚刚加班结束&#xff0c;顺手写了这篇文章。 前言 某大型全国性行业核心系统数据库需要A、B两个物理隔离的双网卡架构方案&#xff0c;已成为行业标准。而最新发布的MogDB 5.0.6的CM新增支持流复制双网段部署&#xff0c;用于网卡级高可用容灾(…

【Linux开发实用篇】备份与恢复

备份 实体机无法做快照&#xff0c;我们可以使用备份和恢复技术 第一种方式 把需要的文件&#xff08;或者分区&#xff09;用TAR打包就好&#xff0c;下次恢复的时候进行解压 第二种方式 使用dump 和 restore 指令&#xff1a; 首先安装这两个指令 yum -y install dump, …

参数传递 的案例

文章目录 12 1 输出一个int类型的数组&#xff0c;要求为&#xff1a; [11,22,33,44,55] package com.zhang.parameter; //有关方法的案例 public class MethodTest3 {public static void main(String[] args) {//输出一个int类型的数组&#xff0c;要求为&#xff1a; [11,…

Android studio顶部‘app‘红叉- Moudle ‘XX.app’ dosen’t exist in project

Android studio顶部app红叉- Moudle ‘XX.app’ dosen’t exist in project 1、现象&#xff1a; 运行老项目或者有时候替换项目中的部分代码&#xff0c;明明没有错但是Android studio就编译报错了。 1.1 Android studio顶部app红叉。 1.2 点击Build没有clear菜单&#xff0…

行为审计软件合集|3款好用的上网行为管控软件推荐

网络技术的快速发展使得企业对于员工上网行为的管控需求也日益增强。 上网行为管控软件不仅可以有效监控员工的网络活动&#xff0c;提高工作效率&#xff0c;还可以防止敏感信息的泄露&#xff0c;保障企业的网络安全。 本文将为您推荐三款好用的上网行为管控软件&#xff1a…

『视觉感官盛宴』3D线上商场全方位展示商品与互动购买体验

随着技术的进步和消费者需求的多样化&#xff0c;3D线上商场作为一种新兴的电子商务平台&#xff0c;正逐渐改变传统的在线购物模式。 一、商品展示革命 在3D线上商场中&#xff0c;商品展示不再局限于静态图片和文字描述。借助先进的3D建模技术&#xff0c;商家能够创建商…

1557.可以到达所有点的最少点数目

题目 给你一个 有向无环图 &#xff0c; n 个节点编号为 0 到 n-1 &#xff0c;以及一个边数组 edges &#xff0c;其中 edges[i] [fromi, toi] 表示一条从点 fromi 到点 toi 的有向边。 找到最小的点集使得从这些点出发能到达图中所有点。题目保证解存在且唯一。 你可以以…

电磁仿真--基本操作-CST-(2)

目录 1. 回顾基操 2. 操作流程 2.1 创建工程 2.2 修改单位 2.3 创建 Shape 2.4 使用拉伸 Extrude 2.5 修改形状 Modify Locally 2.6 导入材料 2.7 材料解释 2.8 材料分配 2.9 查看已分配的材料 2.10 设置频率、背景和边界 2.11 选择 Edge&#xff0c;设置端口 2.…

【网络编程】Java网络编程中的基本概念及实现UDP、TCP客户端服务器程序(万字博文)

系列文章目录 【网络通信基础】网络中的常见基本概念 【网络编程】Java网络编程中的基本概念及实现UDP、TCP客户端服务器程序&#xff08;万字博文&#xff09; 【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制&#xff08;CRC算法、MD5算法&#xff09; 目录 …

公园景区伴随音乐系统-公园景区数字IP广播伴随音乐系统建设指南

公园景区伴随音乐系统-公园景区数字IP广播伴随音乐系统建设指南 由北京海特伟业任洪卓发布于2024年4月23日 随着“互联网”被提升为国家战略&#xff0c;传统行业与互联网的深度融合正在如火如荼地展开。在这一大背景下&#xff0c;海特伟业紧跟时代步伐&#xff0c;凭借其深厚…

linux常用非基础命令/操作

本篇用于总结蒟蒻博主在使用linux系统的过程中会经常用到但老实记不住的一些非基础命令和操作&#xff0c;方便遗忘时查阅 一&#xff0c;关闭指定端口的进程以释放端口 每个端口都有一个守护进程&#xff0c;kill掉这个守护进程就可以释放端口 ①使用命令【netstat -anp | gre…

[大模型]Qwen-Audio-chat FastApi 部署调用

Qwen-Audio-chat FastApi 部署调用 Qwen-Audio 介绍 Qwen-Audio 是阿里云研发的大规模音频语言模型&#xff08;Large Audio Language Model&#xff09;。Qwen-Audio 可以以多种音频 (包括说话人语音、自然音、音乐、歌声&#xff09;和文本作为输入&#xff0c;并以文本作为…

GoJudge环境部署本地调用云服务器部署go-judge判题机详细部署教程go-judge多语言支持

前言 本文基于go-judge项目搭建&#xff0c;由于go-judge官网项目GitHub - criyle/go-judge: Sandbox Server in REST / gRPC API. Based on Linux container technologies.&#xff0c;资料太少&#xff0c;而且只给了C语言的调用样例&#xff0c;无法知道其他常见语言比如&am…

【Unity学习笔记】第十三 · tag与layer(运行时创建tag和layer)

参考&#xff1a; Unity手册 标签Unity手册 LayersIs it possible to create a tag programmatically?脚本自动添加tag和Layer 注&#xff1a;本文使用Unity版本是2022.3.23f1 转载引用请注明出处&#xff1a;&#x1f517;https://blog.csdn.net/weixin_44013533/article/de…

【JavaScriptthreejs】对于二维平面内的路径进行扩张或缩放

目标 对指定路径 [{x,y,z},{x,y,z},{x,y,z},{x,y,z}.........]沿着边缘向内或向外扩张&#xff0c;达到放大或缩小一定范围的效果&#xff0c;这里我们获取每个点&#xff08;这里是Vector3(x,y,z)&#xff09;,获取前后两个点和当前点的坐标&#xff0c;计算前后两点的向量&a…

Ubuntu 安装 Harbor

一、安装 docker 原文参考传送门 1st 卸载系统自带的 docker 应用 for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done 2nd 设置Docker 的apt源 # Add Dockers official GPG key: sudo…

漫谈-AI 时代的信息模型

模型化- 数字化转型的重要基石 在各行各业推行数字化转型过程中&#xff0c;构建信息化模型十分重要&#xff0c;它是数字化转型的基石。事实上&#xff0c;数字化转型的核心是“万物皆模型”&#xff0c;在工业领域&#xff0c;以德国为主导的工业4.0 发展进程中&#xff0c;…