操作系统MIT6.S081:Lab1->Unix utilities

本文介绍MIT6.S081操作系统课程的五个实验:sleep、pingpong、primes、find和xargs。详细阐述每个实验的目的、思路及代码实现。

本系列文章为MIT6.S081的学习笔记,包含了参考手册、课程、实验三部分的内容,前面的系列文章链接如下
操作系统MIT6.S081:[xv6参考手册第1章]->操作系统接口
操作系统MIT6.S081:P1->Introduction and examples


一、sleep

1.1 实验描述

实验目的

为xv6系统实现UNIX的sleep程序。你的sleep程序应该使当前进程暂停指定的时钟周期数,时钟周期数由用户指定。例如执行sleep 100,则当前进程暂停,等待100个时钟周期后才继续执行。时钟周期是xv6内核定义的时间概念,来自计时器芯片的两次中断之间的时间。你的解决方案包含应该在文件user/sleep.c中。

实验提示

1、在开始编程之前,阅读配套手册的第一章。
2、可以参考/user目录下的其他程序(如echo.c、grep.c和rm.c),了解如何获取和传递给程序相应的命令行参数.
3、如果用户传入参数有误,即没有传入参数或者传入多个参数,程序应该能打印出错误信息。
4、通过字符串传递命令行参数。可以通过atoi(详情见user/ulib.c)函数将字符串转换为整数
5、使用系统调用sleep
6、有关实现sleep系统调用的xv6内核代码(sys_sleep),请参考kernel/sysproc.c。有关可从用户程序调用sleep的C 定义在user/user.h中,以及有关汇编代码的user/usys.S 从用户代码跳转到内核进行睡眠。
7、确保main函数调用exit()以退出程序。
4、实现的程序应该命名为sleep.c并最后放入user目录下。
8、将你的sleep程序添加到Makefile的UPROGS中。只有这步完成后,make qemu才能编译你写的程序,你才能在shell中运行这个程序。
9、通过Kernighan和Ritchie’s的The C programming language(第2版)学习C语言

测试条件

①在xv6的shell中运行该程序
在这里插入图片描述
②如果通过上述命令使程序停止10个时钟周期,则说明你的方案是正确的。运行make grade查看你是否通过了测试。
注:make grade会运行所有测试程序,如果你只想测试当前程序,可以指定要运行的程序,通过以下命令:
在这里插入图片描述
你也可以通过下面这条命令测试当前程序
在这里插入图片描述


1.2 实验思路

头文件

系统调用sleep的声明在user/user.h中。
在这里插入图片描述
user.h中的一些系统调用函数声明使用了一些数据类型,这些数据类型在kerner/type.h中声明。
在这里插入图片描述

命令行参数判断

如果命令行参数有错误,则通过write或fprintf输出错误信息
然后通过exit退出

执行sleep操作

①通过atoi将argv[1]参数转换为整数
②调用系统调用函数sleep执行中断操作
③通过exit退出


1.3 实验代码

整体代码如下

#include "kernel/types.h" //一些数据类型声明
#include "user/user.h" //用户可以使用的系统调用声明

int main(int argc, char* argv[])
{
   
   
    if (argc != 2){
   
     //命令行参数不为2
    	//也可以调用write
       fprintf(2, "Usage: sleep <num> \n"); //将提示信息写入标准错误端
       exit(1);	 //退出,参数1表示非正常退出
    }
    int number = atoi(argv[1]); //将字符串转为整数
    sleep(number); //调用系统调用sleep
    exit(0); //正常退出
}

测试

①首先在makefile文件中添加$U/_sleep\
在这里插入图片描述
②然后sudo make qemu进入xv6
③在终端中测试sleep
在这里插入图片描述
④退出xv6,在shell中通过./grade-lab-util sleep测试
在这里插入图片描述
注: 如果运行命令./grade-lab-util sleep报/usr/bin/env: ‘python’: No such file or directory错误,可能是因为没装python2或者装的是python3,使用命令vim grade-lab-util,把第一行的python改为python3。如果系统没装python3,则通过命令sudo apt-get install python3安装python3。


二、pingpong

2.1 实验描述

实验目的

使用UNIX系统调用编写一个程序pingpong,在一对管道上实现两个进程之间的通信。父进程通过第一个管道给子进程发送一个信息“ping”,子进程接收父进程的信息后打印"<pid>: received ping" ,其中pid是子进程的ID。然后子进程通过另一个管道发送一个信息“pong”给父进程,父进程接收子进程的信息然后打印"<pid>: received pong",其中pid是父进程的ID,然后退出。

实验提示

1、通过pipe创建一个管道
2、通过fork创建一个子进程
3、通过read从管道中读取数据,通过write向管道中写入数据
4、通过getpid获取当前进程的pid
5、将程序添加到Makefile文件中的UPROGS中
6、xv6上的用户程序拥有一些库函数可供使用,你可以在user/user.h中查看这些函数对应的列表。除系统调用外其他函数的源代码位于user/ulib.c、user/printf.c和user/umalloc.c中。

测试条件

在shell中运行程序并将得到以下结果
在这里插入图片描述
如果你的程序在两个进程间传递信息并产生以上结果,则说明你的方案正确。


2.2 实验思路

初始化

创建父进程、子进程的文件描述符数组
父进程、子进程创建管道
创建缓冲区字符数组buf,存放要传递的信息
通过fork创建子进程

父进程

①关闭父进程管道的读取端
②将"ping"通过父进程管道的写入端进行写入
③关闭子进程管道的写入端
④从子进程管道的读取端读取信息到buf中
⑤打印收到的信息

子进程

①关闭父进程管道的写入端
②子进程从父进程管道的读取端读取数据
③打印收到的信息
④关闭子进程管道的读取端
⑤将子进程管道的写入端信息写入buf中


2.3 实验代码

整体代码如下

#include "kernel/types.h"
#include "user/user.h"

int main()
{
   
   
    int pfd[2];  //父进程的文件描述符数组
    int cfd[2];  //子进程的文件描述符数组
    pipe(pfd);   //父进程创建管道
    pipe(cfd);   //子进程创建管道
    char buf[10];  //缓冲区字符数组,存放传递的信息
    int pid = fork(); //创建子进程

    if(pid < 0){
   
   
        fprintf(0, "fork error\n");
        exit(1); //创建子进程错误
    }
    else if(pid == 0){
   
    //子进程
        close(pfd[1]); //关闭父进程管道的写入端
        read(pfd[0], buf, 4); //将父进程管道的读取端数据读取到buf中
        printf("%d: received %s\n", getpid(), buf); //打印收到的信息
        close(cfd[0]); //关闭子进程管道的读取端
        write(cfd[1],"pong", 4); //将"pong"写入子进程管道的写入端
    }else{
   
    //父进程
        close(pfd[0]); //关闭父进程管道的读取端
        write(pfd[1], "ping", 4); //将"ping"写入父进程管道的写入端
        close(cfd[1]); //关闭子进程管道的写入端
        read(cfd[0], buf, 4); //将子进程管道的读取端信息读取到buf中
        printf("%d: received %s\n", getpid(), buf); //打印收到的信息
    }

    exit(0); //正常退出
    return 0;
}

测试

①首先在makefile文件中添加$U/_pingpong\
②然后sudo make qemu进入xv6
③在终端中测试pingpong

MIT 6.S081 是麻省理工学院开设的一门关于操作系统的课程,课程全称为 **MIT 6.S081: Operating System Engineering**。该课程以实践为导向,通过让学生从零开始逐步构建一个简单的类 Unix 操作系统内核(基于 RISC-V 架构),深入理解操作系统的核心原理和实现机制。 课程内容涵盖线程、调度、虚拟内存、文件系统、系统调用、中断、设备驱动、同步机制等操作系统关键主题。课程材料公开,包括讲义、实验(labs)、视频讲座和源代码,非常适合自学。 ### 课程资源获取方式 1. **官方网站** MIT OpenCourseWare 提供了完整的课程材料,包括实验指导、源代码、讲义和部分视频讲座。 - 官网地址:[https://pdos.csail.mit.edu/6.828/2020/index.html](https://pdos.csail.mit.edu/6.828/2020/index.html) (注意:6.S0816.828 的新编号,内容基本一致) 2. **XV6 操作系统源码** 课程使用 xv6 作为教学操作系统,它是 Unix V6 的简化版,使用 C 语言编写,适合教学和学习。 - 源码地址:[https://github.com/mit-pdos/xv6-riscv](https://github.com/mit-pdos/xv6-riscv) 3. **实验(Labs)** 课程实验包括: - **Lab 1: Xv6 and Unix utilities** - **Lab 2: System calls** - **Lab 3: Page tables** - **Lab 4: Traps** - **Lab 5: Threads** - **Lab 6: Locking** - **Lab 7: File system** - **Project: Networking (optional)** 每个实验都要求修改 xv6 源码以实现特定功能,例如添加系统调用、实现线程调度、实现文件系统操作等。 4. **社区与讨论区** - **GitHub 项目**:许多学生将他们的实验成果上传到 GitHub,可以参考他们的实现思路和代码。 - **Reddit 和 Stack Overflow**:在 r/mit、r/operatingsystems 和 Stack Overflow 上可以找到相关讨论和问题解答。 - **知乎、优快云 等中文社区**:一些中文用户也分享了他们对 MIT 6.S081 的学习笔记和实验解析。 5. **学习建议** - 熟悉 C 语言和汇编基础。 - 掌握基本的数据结构(如链表、队列、树等)。 - 理解计算机体系结构(特别是 RISC-V)。 -操作系统基础理论知识(如进程、内存管理、文件系统等)。 ### 示例代码:添加系统调用 以下是一个简单的系统调用示例,用于在 xv6 中添加一个新的系统调用 `sys_helloworld`: ```c // user/user.h int helloworld(void); // user/usys.pl entry("helloworld"); // kernel/syscall.h #define SYS_helloworld 22 // kernel/syscall.c extern uint64 sys_helloworld(void); // kernel/sysproc.c uint64 sys_helloworld(void) { printf("Hello, world from kernel!\n"); return 0; } ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知初与修一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值