MIT6.828实验:Xv6 and Unix utilities

2023MIT6.828 lab-1

官方地址

一、sleep

实验内容

  • 调用sleep(系统调用)编写用户级别程序
  • 能暂停特定时常的系统滴答
  • 程序保存在user/sleep.c

实验过程

xv6的参数传递

查看官方文档提示的文件中,多采用如下定义:

int main(int argc, char *argv[])
在xv6操作系统中:
1、argc 是一个常见的参数,用于表示传递给程序的命令行参数的数量。 
2、argv(argument vector)是一个指向字符指针数组的指针,该数组中的每个元素都是一个指向命令行参数的字符串的指针。
3、程序的内部可通过argc和argv来访问外界输入的参数
注意:
1、argc指示出程序执行时传入的参数个数,常可用来判断输入是否符合要求
2、argv[]为存放字符指针的数组,我们需要的是其指向地址存放的数据,若要当整型数据使用还需进行相应转换

实现代码

#include "kernel/types.h"     //调用相应的头文件
#include "kernel/stat.h"
#include "user/user.h"
int main( int argc ,char *argv[])  //通过argc和argv传入参数
{if(argc!=2)   //传入参数数量不符合{fprintf(2,"usage:sleep time\n");exit(1);}
sleep(atoi(argv[1]));  //由于argc[]指向字符型数据,调用atoi()进行转换
fprintf(2,"nothing happens for a little while\n");
exit(0);  //退出程序
}

编译准备

在make qemu之前,还需进行将编写的sleep()程序加入编译文件中:

1、进入lab目录下
vi Makefile  //打开文件
: ?UPROGS   //vim下搜索关键词2、定位到UPROGS,在最后一处按格式补入sleep():
UPROGS=\$U/_cat\$U/_echo\$U/_forktest\$U/_grep\$U/_init\$U/_kill\$U/_ln\$U/_ls\$U/_mkdir\$U/_rm\$U/_sh\$U/_stressfs\$U/_usertests\$U/_grind\$U/_wc\$U/_zombie\$U/_sleep\3、保存退出

编译运行

make qemuxv6 kernel is booting
hart 1 starting
hart 2 starting
init: starting sh
$ sleep 10
nothing happens for a little while  //停顿后显示,达到实验效果

工具测试

在lab目录下执行:
$ ./grade-lab-util sleep
或
$ make GRADEFLAGS=sleep grade

输出:
在这里插入图片描述
测试通过

二、pingpong

实验内容

  • 在父进程中创建子进程
  • 编写用户级程序调用系统调用通过一对pipes在两个进程间实现’‘ping-pong’’ 一个字节
  • 父进程给子进程发送一字节,子进程收到后print “: received ping” 这里的 is its process ID,并通过pipes给父进程传递一字节,然后exit
  • 父进程读取来自子进程的字节,并print “: received pong”,然后exit
  • 程序保存在user/pingpong.c

实验过程

fork用法

打开/kernel/proc.c查看fork()源码

// Create a new process, copying the parent.
// Sets up child kernel stack to return as if from fork() system call.
int
fork(void)
{int i, pid;struct proc *np;struct proc *p = myproc();// Allocate process.if((np = allocproc()) == 0){return -1;}// Copy user memory from parent to child.if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){freeproc(np);release(&np->lock);return -1;}np->sz = p->sz;// copy saved user registers.*(np->trapframe) = *(p->trapframe);// Cause fork to return 0 in the child.np->trapframe->a0 = 0;// increment reference counts on open file descriptors.for(i = 0; i < NOFILE; i++)if(p->ofile[i])np->ofile[i] = filedup(p->ofile[i]);np->cwd = idup(p->cwd);safestrcpy(np->name, p->name, sizeof(p->name));pid = np->pid;release(&np->lock);acquire(&wait_lock);np->parent = p;release(&wait_lock);acquire(&np->lock);np->state = RUNNABLE;release(&np->lock);return pid;
}
该函数的作用:
1、创建一个新进程,并复制父进程的内容
2、为子进程(child process)设置内核栈(kernel stack),以便在子进程执行完毕后,其行为表现得就像是从 fork() 系统调用返回一样
3、父子进程内容相同(除个别数据),但内存空间不同,修改互不影响
4、在父进程中,fork()返回新创建的子进程的进程ID;在子进程中,fork()返回0;如果发生错误,则返回-1

结构体proc的声明
该结构体存储了每一个进程的信息

// Per-process state
struct proc {struct spinlock lock;// p->lock must be held when using these:enum procstate state;        // Process statevoid *chan;                  // If non-zero, sleeping on chanint killed;                  // If non-zero, have been killedint xstate;                  // Exit status to be returned to parent's waitint pid;                     // Process ID// wait_lock must be held when using this:struct proc *parent;         // Parent process// these are private to the process, so p->lock need not be held.uint64 kstack;               // Virtual address of kernel stackuint64 sz;                   // Size of process memory (bytes)pagetable_t pagetable;       // User page tablestruct trapframe *trapframe; // data page for trampoline.Sstruct context context;      // swtch() here to run processstruct file *ofile[NOFILE];  // Open filesstruct inode *cwd;           // Current directorychar name[16];               // Process name (debugging)
};

pipes用法

pipe()函数定义

int pipe(int p[])  Create a pipe, put read/write file descriptors in p[0] and p[1]. 
1、调用pipe函数来创建一个新的管道。如果成功,pipe函数返回0,并将两个文件描述符分别存放在p[0]和p[1]中。如果失败,返回-1。
2、pipe为半双工通信,要根据实际指定通信方向,关闭管道的读或写,保留另一功能
3、可采用两条pipe实现互通

在这里插入图片描述

getpid用法

获取当前进程PID
int getpid()  Return the current process’s PID. 

实现代码

注意:读写顺序
#include "kernel/types.h"
#include "user/user.h"int main(int argc,int *argv[])
{int ptc_pipe[2];int ctp_pipe[2];pipe(ptc_pipe); //父to子pipe(ctp_pipe);//子to父int pid;pid = fork(); //新建子进程if(pid==0) //处于子进程{//设定管道通信方向close(ptc_pipe[1]); //子读取close(ctp_pipe[0]); //子写入char buff[16];if( read( ptc_pipe[0],buff,1) ==1 ) //子进程收到父进程的一字节{printf("%d: received ping\n",getpid() );}write( ctp_pipe[1],"p",1 ); //往父进程发送一字节exit(0);}else //处于父进程{//设置管道方向close( ptc_pipe[0] );// 父写入close( ctp_pipe[1] );// 父读取write( ptc_pipe[1],"p",1 ); //往子进程发送一字节char buff[16];if( read( ctp_pipe[0],buff,1)==1 )//父进程读取到一字节{printf("%d: received pong\n",getpid() );}}
exit(0);
}

编译准备

往Makefile中UPROGS=\项目添加  $U/_pingpong\

运行结果

在这里插入图片描述

工具测试

make GRADEFLAGS=pingpong grade

在这里插入图片描述
测试通过

三、primes

实验内容

1、在xv6中使用pipe编写一个并发的素数筛选程序
2、使用pipe和fork来建立管道
3、第一个进程向管道内输入数字2到35
4、对于每个素数,创建一个进程来从管道左侧读取,并传输给另一条管道右侧
5、受限于xv6的有限文件描述符和进程,第一个进程将在35处停止
6、程序位于user/primes.c

实验过程

过程分析

1、采用pipe进行数字传递,用fork创建下一级,直到结束
2、每级中挑选出一个素数,把剩余经过此素数处理过的传递到下一级
3、传递后父进程要执行等待子进程结束的操作

实现代码

注意:
1、仔细关闭程序不需要的文件描述符,否则在35前xv6的资源会耗尽
2、pipe用完关闭,避免拥塞
3、注意pipe和fork执行顺序
#include "kernel/types.h"
#include "user/user.h"int children( int ptc_pipe[])
{//设置管道方向close( ptc_pipe[1] );//子读取,不需要写入//对父到子管道进行检查int num;if( read( ptc_pipe[0] ,&num,sizeof(num)) == 0 ) //管道空{close( ptc_pipe[0]);exit(0);}else{printf("prime %d\n",num); //打印素数}//创建孙进程int pid;int ctg_pipe[2];pipe( ctg_pipe );//子进程到孙进程管道pid=fork();if( pid==0 ) //孙子进程{children( ctg_pipe );  //递推}else  //子进程{//设置子到孙管道方向close( ctg_pipe[0] );//子写孙读int i;while( read( ptc_pipe[0],&i,sizeof(i))>0 ) //管道还有数据{if( i % num !=0 )//有余数write( ctg_pipe[1],&i,sizeof(i) );//发送到下一级}close( ctg_pipe[1]);//关闭写,避免读拥塞wait(0); //等待孙进程结束}exit(0);//结束返回}
int main(int argc,int *argv[])
{int ptc_pipe[2];//建立第一个管道pipe(ptc_pipe);int pid;pid =fork(); //创建子进程if( pid==0 ) //位于子进程{children(ptc_pipe); //函数反复调用}else //位于父进程{//管道设置close(ptc_pipe[0]); //父写入,不需要读取for(int i=2;i<=35;i++) //往管道输入数字{write(ptc_pipe[1],&i,sizeof(i));}close( ptc_pipe[1]);//关闭写,避免读拥塞wait(0);//等待子进程}
exit(0);
}

编译准备

往Makefile中UPROGS=\项目添加  $U/_primes\

运行结果

在这里插入图片描述

工具测试

 make GRADEFLAGS=primes grade

在这里插入图片描述
测试通过

find

实验内容

实验过程

工具测试

更新中

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

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

相关文章

【网站项目】三省学堂-学习辅助系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Redis中的Sentinel(一)

Sentinel 概述 Sentinel(哨岗、哨兵)是Redis的高可用性(high availability)解决方案:由一个或多个Sentinel实例(instance)组成的Sentinel系统(system)可以监视任意多个主服务器&#xff0c;以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时&#xff0…

OpenEuler/Centos制作离线软件源

需求背景&#xff1a; 一般线上服务器都是不能连接外网&#xff0c;服务器安装好系统之后就需要部署相关软件&#xff0c;此时因为无法联网导致无法下载软件&#xff0c;所以都会做一个本地的离线软件源&#xff0c;本文简单介绍如何快速利用已经下载好的rpm包&#xff0c;制作…

【C++】编程规范之性能优化

性能优化流程 找到性能热点代码 在进行性能优化之前&#xff0c;首先需要确定哪些部分是代码的性能热点。可以使用性能分析工具&#xff08;如 simpleperf&#xff09;生成火焰图&#xff0c;识别程序中的瓶颈。 确定性能问题、原因和优化方案 通过分析火焰图&#xff0c;确定…

JAVA毕业设计133—基于Java+Springboot+Vue的网上宠物店商城管理系统(源代码+数据库+12000字论文)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的网上宠物店商城管理系统(源代码数据库12000字论文)133 一、系统介绍 本项目前后端分离&#xff0c;分为管理员、用户两种角色 1、用户&#xff1a; 注册…

python-基础篇-字符串、列表、元祖、字典-字符串

文章目录 2.3字符串、列表、元祖、字典2.3.1字符串2.3.1.1字符串介绍2.3.1.1.1python中字符串的格式&#xff1a;2.3.1.1.2字符串在内存中的存储方式 2.3.1.2字符串的输入输出2.3.1.2.1字符串输出2.3.1.2.2字符串输入2.3.1.2.3组字符串的方式 2.3.1.3下标和切片2.3.1.3.1下标索…

Android 系统大致启动流程

Android启动流程大体为&#xff1a;BootRom -> BootLoader -> Kernel -> Init -> Zygote -> SystemServer ->Launcher 1、Loader层 1.1、Boot ROM 电源按下&#xff0c;引导芯片代码开始从预定义的地方&#xff08;固化在ROM&#xff09;开始执行&#xff0…

Unity入门

Unity入门学习 知识概述&#xff1a; Unity环境搭建 1.Unity引擎是什么 2.软件下载安装 下载最新的长期支持版即可 3.新工程和工程文件夹 Unity界面基础 1.Scene场景和Hierachy层级窗口 练习&#xff1a; 2.Game游戏和Project工程 3.Inspector检查和Console控制台 练习&#…

医疗器械5G智能制造工厂数字孪生可视化平台,推进行业数字化转型

医疗设备5G智能制造工厂数字孪生可视化平台&#xff0c;推进行业数字化转型。在数字化浪潮的推动下&#xff0c;医疗设备行业正迎来一场深刻的变革。5G技术的崛起&#xff0c;智能制造工厂的兴起&#xff0c;以及数字孪生可视化平台的出现&#xff0c;正在共同推动医疗设备行业…

英语语法总结(1)

名词 &#xff08;1&#xff09;专有名词China &#xff08;2&#xff09;普通名词{ 个体名词horse 集体名词people 物质名词fire 抽象名词labor }可数名词{ 个体名词a book 集体名词 My family is a large one(整体) My family are all music lovers(个体) &#xff08;若作为…

编程基础---C/C++基础知识

语法和语义 变量定义 基本数据类型&#xff1a;定义整型&#xff08;int、long、short&#xff09;、浮点型&#xff08;float、double&#xff09;、字符型&#xff08;char&#xff09;等基本数据类型的变量。 自定义类型&#xff1a;定义结构体、联合体、枚举等自定义类…

react组件:profiler

React Profiler 主要用于开发过程中的性能分析和优化&#xff0c;而不应在生产环境中使用&#xff0c;因为它可能会对性能产生一定的影响。 使用 包裹组件树&#xff0c;以测量其渲染性能。 ** id&#xff1a;字符串&#xff0c;用于标识正在测量的 UI 部分。 onRender&a…

Xshell Plus 详细安装教程以及附带使用图文教程

一、下载 Xshell Plus 6 完成后&#xff0c;请按照下面教程操作 1、下载 Xshell Plus 6 完成后&#xff0c;并解压 zip 包: 2、进入解压后的文件夹后&#xff0c;如果你之前安装了 Xshell&#xff0c; 先点击 !卸载.bat 卸载 xshell&#xff0c; 然后再点击 !绿化.bat; 如果是…

二分答案(砍树,借教室)

二分的两种情况附代码&#xff1a; 二分查找条件&#xff1a;单调&#xff0c;二段性 例题1&#xff1a;P1873 [COCI 2011/2012 #5] EKO / 砍树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 上代码&#xff1a; #include<bits/stdc.h> using namespace std; const …

校招说明书

3400字的详细说明&#xff0c;介绍了程序员类岗位校招的整体时间节点和招聘流程。还对一些常见的问题进行讨论&#xff0c;例如内推、offer和三方、实习等。 第一章介绍基本的术语&#xff0c;第二章介绍整个校招的重要流程及时间点&#xff0c;然后第三章介绍每次招聘要经过的…

什么是jQuery?怎么使用?

​ 文章目录 一、jQuery是什么二、dom对象和jQuery对象1、DOM对象可以和jQuery对象相互的转换 三、基本选择器1、元素选择器&#xff1a;根据HTML元素的名称选择元素2、ID选择器&#xff1a;通过元素的ID属性选择元素3、类选择器&#xff1a;通过元素的class属性选择元素4、通…

MySql 实战大数据查询-(表分区实现)

一 mysql分区&#xff1a; 分区是将单个表按照某种规则划分成多个子集&#xff0c;每个子集称为一个分区。常见的分区策略包括按照时间范围、范围值、列表等进行分区。 优点&#xff1a; 查询性能更好&#xff0c;涉及分区键的查询&#xff0c;数据库引擎可以只扫描特定分区&…

易宝OA ExecuteQueryForDataSetBinary SQL注入漏洞复现

0x01 产品简介 易宝OA系统是一种专门为企业和机构的日常办公工作提供服务的综合性软件平台,具有信息管理、 流程管理 、知识管理(档案和业务管理)、协同办公等多种功能。 0x02 漏洞概述 易宝OA ExecuteQueryForDataSetBinary 接口处存在SQL注入漏洞,未经身份认证的攻击者…

Word中插入Endnote参考文献时显示乱码

近期在写文章需要插入参考文献&#xff0c;使用Endnote插入时显示乱码&#xff0c;如下图所示&#xff1a; 文章末尾显示{ADDIN EN REFILIST } 解决方法 在网上找了诸多方法尝试也没有解决&#xff0c;最终找到一篇博客介绍了一种方法&#xff1a; word选项—高级&#xff1…

openGauss学习笔记-256 openGauss性能调优-使用Plan Hint进行调优-优化器GUC参数的Hint

文章目录 openGauss学习笔记-256 openGauss性能调优-使用Plan Hint进行调优-优化器GUC参数的Hint256.1 功能描述256.2 语法格式256.3 参数说明 openGauss学习笔记-256 openGauss性能调优-使用Plan Hint进行调优-优化器GUC参数的Hint 256.1 功能描述 设置本次查询执行内生效的…