操作系统6.s081Lab 1 完成记录 | 笔记

194 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

注:本实验完成周期较长,前半部分摘自本人此前发表在CSDN上的博客文章,后半部分首发于稀土掘金平台。

sleep

环境配置

租了个腾讯云服务器,并将系统设为教程推荐的ubuntu 20.4版本,具体配置细节lab要求里的“lab tools page”有很详细的介绍,这里不再赘述。

Boot xv6

  • 在执行$ git clone git://g.csail.mit.edu/xv6-labs-2021命令时,提示我没有clone权限。

遇到这种情况只需要返回上级目录,然后将打算用于存放仓库代码的目录的权限设为o+w即可。 代码:

sudo chmod o+w dirname

dirname为存放仓库代码的目录

  • 生成和运行xv6是以下命令:
make qemu

之后可以进入xv6,这是一个类Unix的操作系统,我们之后的任务就是往其中增加功能。

  • 接下来先熟悉一下这个操作系统: 先试试ls 命令 (注:我是先做了sleep功能再写这篇文章,所以此处显示有sleep,一开始打开的时候是没有的)

在这里插入图片描述 试试echo:

echo hello world!

在这里插入图片描述 试试mkdir:

mkdir test

在这里插入图片描述 不过有点bug,我cd进去该目录之后无法使用功能命令了

在这里插入图片描述 对此,我在xv6的课本中找到了这样一段描述,不知道会不会和这个有关系: 在这里插入图片描述 在这里插入图片描述 一方面和cd本身的机制有关,另一方面是因为xv6还没能像Unix一样完善。

  • 关于退出: lab要求中有这样的提示: 在这里插入图片描述 我试了试,指的是在同时按下ctrl和字母a键之后快速松手并马上按x键。

关于实现sleep功能:

  • 在user/ 下新建sleep.c文件并打开:(使用vim打开一个不存在的文件将会自动创建)
vim sleep.c
  • 编写代码 参照教程提示: 在这里插入图片描述 代码如下:
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int main(int argc, char *argv[]){
    int n;
    if (argc != 2){
        fprintf(2, "Please enter a number!\n");
        exit(1);
    }else{
        n = atoi(argv[1]);
        sleep(n);
        exit(0);
    }
}

关于功能添加与评测

  • 在.c文件写好代码之后,还要把它添加到功能列表中。在这里插入图片描述 返回上级目录,打开Makefile文件,在UPROGS配置下追加一行代码。 (写到这里的时候没打开相应文件,就不放代码了,不过很简单的,上面的指令什么格式,这个依葫芦画瓢就行) (vim操作回顾:在normal模式下输入/可以搜索关键词,按n查找下一个结果,按N查找上一个结果)

  • 之后make qemu,会看到如下结果: 在这里插入图片描述 输入ls可以看到ls出现在选项中,如前面的图展示的。

  • 来试试功能: 在这里插入图片描述 输入该命令后,可观察到几秒内 光标在闪烁,但是没有其他的东西,新的$也没出现,说明进程确实是在休眠。

  • 评测 在这里插入图片描述 这个make grade命令出现在sleep功能要求之前,好奇宝宝本人手贱没看清楚说明就输入了,结果评测出0分 (现在知道它的含金量了吧?指的是当前lab的所有测试)。

如果做完了其中一个,比如只完成了sleep功能,想只测sleep的,可以使用这个命令:

 $ ./grade-lab-util sleep

或者这个:

$ make GRADEFLAGS=sleep grade

我看网上有博客文章说要改这个评测脚本的测试路径和测试命令,但我试了试,反正我这边不改也行的。

结果

在这里插入图片描述 看到评测结果,还是很有成就感滴!

pingpong

背景知识

管道可用于进程间通信。

  • 从管道一端写入数据(write,文件描述符为 1)),数据在管道中流动,可从另外一端被读取(read, 文件描述符为 0)。
  • 数据读取或写入的时候,另一端的管道会被 关闭 。
  • fork()之后,子进程的pid为0,父进程的pid为原来的,两者互不干扰。

代码

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

int main(int argc,char *argv[]){
    int p1[2];
    int p2[2];
    int pid;
    char buf[1];                                                                                                                   

    pipe(p1);
    pipe(p2);
    pid=fork();

    if(pid<0) exit(1);
    else if(pid==0){
        close(p1[1]);
        close(p2[0]);
        read(p1[0],buf,1);
        printf("%d: received ping\n",getpid());
        write(p2[1]," ",1);
        close(p1[0]);
        close(p2[1]);
           }else{
        close(p1[0]);
        close(p2[1]);
        write(p1[1]," ",1);
        read(p2[0],buf,1);
        printf("%d: received pong\n",getpid());
        close(p1[1]);
        close(p2[0]);
    }
        exit(0);
}                             

一点额外收获(vim相关)

其实这个实验本身是easy程度,不过因为比较头铁,想要直接在vim里面写代码,所以在折腾它的过程中学到了很多vim操作。

关于vim配置:

我想要给文本设置行号,让vim像vscode一样支持符号匹配,代码缩进,于是在~/.vimrc文件中写入如下代码: (参考这篇文章:www.cnblogs.com/write-hua/p…

set nu

set smartindent

:inoremap ( ()<ESC>i

:inoremap ) <c-r>=ClosePair(')')<CR>

:inoremap { {<CR>}<ESC>O

:inoremap } <c-r>=ClosePair('}')<CR>

:inoremap [ []<ESC>i

:inoremap ] <c-r>=ClosePair(']')<CR>

:inoremap " ""<ESC>i

:inoremap ' ''<ESC>i

比如我后面想要全选文本,如果直接选中文本,会把行号也选中,那就要对 本文件 取消行号: 在命令行模式下:

:set nonu

关于vim模式

在写代码的过程中对vim模式有了更清晰直观的认识。(以下是我本次用到的) 在这里插入图片描述

primes

思路

教程中提到的论文是这么写的:

image.png

一开始读入所有的数,2是素数,打印它,判断进程管道中的其他数是否能被该数整除,如果不能(说明可能是素数),fork一个子进程,把数传过去(递归实现该过程,也做到了实验要求中的连接管道的左边和右边),这样一层一层传,并打印出当前进程最小的数(一定是素数),结束条件是达到35这个数。

注意要及时关闭管道不用的端。

代码截图

(发现在 独立的 Linux系统写代码,然后想复制vim中的代码到外部始终很麻烦,那就这样吧,我截个图算了) 声明及主函数 在这里插入图片描述 子函数:递归操作,数的整除操作 在这里插入图片描述

额外收获

  • 才知道vim的复制粘贴(yy p)最多只支持50行代码(应该是寄存器容量的原因吧)

注意!!接下来的两个实验都是应该先make clean ,再make qemu!!!

find

评测效果

image.png

代码截图

(从服务器里的vim里复制粘贴代码真的太难了,一次只能选中当前页面范围的,手滑还容易无,真是谁用谁知道,我还是贴图叭)

  • 教程提到读取目录操作可以参考user/ls.c的代码,其实可以大段大段地用相应代码,只需要改改参数,具体内容修改一点点。

image.png image.png 教程说字符串不要用==,用strcmp image.png image.png

vim技巧篇:

  • 替换 当前行 整个单词:(命令行模式下)
: s /ori/new 

ori为原单词,new为替换后的单词

  • 对当前文件启用鼠标复制粘贴:(命令行模式下)
set mouse-=a

我的理解是这里的a指的是all,就是原本键盘能有的功能鼠标也能有(mouse=a),但是我们不会用,反而觉得鼠标啥也干不了了,于是现在把这个功能禁止掉,就反而觉得可以复制粘贴了。

  • 把当前vim文件的行号去掉
set nonu

(no number的意思,同理,set nu就是显示行号)

xargs

注意事项

  • 教程里有这样一句话: image.png 要注意对分隔命令的回车进行处理。
  • kernel/param.h中的 MAXARG:32

代码截图及解析

(尝试理解看懂大佬的代码)

  • command指针会依次指向xargs后接的每条命令。
  • bf:buffer
  • paramv:用于存放命令信息的数组空间
  • count:命令条数,遇到空格会加一
  • cursor:游标,用于记录读取某条命令的单个字符的位置,每读到一个新命令,游标会置0
  • flag:当当前为空格且前面有参数的时候flag为1 image.png
  • 读取命令,循环结束条件是读取完毕且用户按下回车

image.png

  • 如果已经读取完了就跳出整个while循环
  • 通过创建子进程去执行任务,否则等待 image.png

运行结果截图

image.png

image.png

为什么会有这么多 $ 呢?

教程里说是因为shell内核以为这些命令来源于终端(而不是实际上的只从文件中读取),所以给每条命令都附上了$。

参考资料

樊潇大佬的博客:fanxiao.tech/posts/MIT-6…