MIT6.S081

MIT6.S081笔记——写写OS

深陷脊背的腐烂禁

深陷脊背的腐烂禁

人生浪费指南三流写手/吃肉肉

2 人赞同了该文章

MIT 6.S081

lab tool

环境要求主要是3个项目:

一个是riscv64的toolchain,另一个就是虚拟机qemu,剩下的就是一个源码库,装好这三个就可以开始写代码了

关于环境一些坑

首先就是toolchain,这个项目仅仅源代码就有3个多G,按照国内访问git的速度几乎不可能下载完,(这个项目是一个套娃项目,其中里面的子module对应着github上的别的项目,其中qemu的部分还不是在github的服务器上,需要请求另一个美国的服务器,即使翻墙走代理速度也是慢的离谱)
解决方法:
1.翻墙走代理,对git进行配置,该项目是套娃项目所以在clone时要进行–recursive.
2.使用网上的百度云,没会员也是慢的离谱,https://zhayujie.com/mit6828-env.html 中有博主分享的百度云链接,加上会员很丝滑
配置好之后编译大约个把小时

Lab: Xv6 and Unix utilities

Boot xv6

这部分主要介绍的就是如何编译,如何使用qemu运行程序,通过Makefile文件在UPROGS加上自己的文件进行编译用户程序,使用make grade进行打分

sleep

这部分代码倒是不难,可以直接对sleep进行系统调用

pipe

这里使用管道对父子进程进行ipc,逻辑上也不难

primes

这个模块很有意思,要求实现一个并发的素数筛,网页给了一个csp的论文进行参考
其中素数筛得基本思路也就是多开线程每个线程筛一个质因子,然后把没有被筛掉的数字向子进程write然后通过进程的不断fork达到一个素数筛的目的
一个错误我卡了很久,就是没有检测read函数的返回值,我认为既然read函数是阻塞io既然没读到就会持续地阻塞下去,实际上不是
并发素数筛的核心逻辑

while(1)
{//child thread
    parent_fd[0]=child_fd[0];
    close(child_fd[1]);
    pipe(child_fd);
    buffer_num=0;
    if(read(parent_fd[0],&buffer_num,sizeof(buffer_num))==0)
    {
        exit();
    }
    //printf("sta=%d %d\n",sta,parent_fd[0]);
    thread_num=buffer_num;
    //int pid=getpid();
    printf("prime %d\n",thread_num);
    if(fork())//parent thread
    {
        close(child_fd[0]);
        while(read(parent_fd[0],&buffer_num,sizeof(buffer_num))==4)
        {
            if(buffer_num%thread_num)
            {
                //pid=getpid();
                //printf("write buffer_num=%d thread_num=%d,pid=%d\n",buffer_num,thread_num,pid);
                write(child_fd[1],&buffer_num,sizeof(buffer_num));
            }
        }
        exit();
    }

pipe

关于pipe的一段代码

int p[2]; 
char *argv[2];
argv[0] = "wc"; 
argv[1] = 0;
pipe(p); 
if(fork() == 0) {
	close(0);
	dup(p[0]); 
	close(p[0]); 
	close(p[1]); 
	exec("/bin/wc", argv);
} else 
{ 
	write(p[1], "hello world\n", 12); 
	close(p[0]); 
	close(p[1]);
}

这是一段很有意思的代码
这段代码通过pipe,close和dup成功把wc的标准输入绑定到了另一个程序的管道中
阻塞read直到不可能到达新数据的一个原因是在执行wc之前,让子进程关闭管道的写入端非常重要。因为如果wc的一个文件描述符指向了管道的写入端,wc将永远不会看到文件末尾。

find

ls 的递归版使用dfs搜索所有的文件夹
其中目录是一种特殊的文件
注意不能递归./ ../否则会无限递归

xargs

这个程序可以执行shell命令 并且把这个程序的标准输入当作argv传入执行的shell
可以用来使用管道把别的程序的输出用管道成为另一个程序的参数
注意好处理字符串 使用fork配合exec即可实现

xv6 shell

features

1.可以调用一些用户态的程序
2.允许cd切换目录
3.对调用的程序传参
4.使用|进行输出输入和管道的绑定
5.使用<>进行io重定向
6.使用&后台运行
7.使用;分割指令从做到右依次执行

shell只是一个用户程序,而不是内核的一部分,shell没有什么特别之处反倒说明了系统调用接口的力量。

完成以上的features就符合了shell的基本需求,正要写一个shell,参考xv6的shell源码,下面从整体上来记录一下xv如何实现shell

parser

还记之前ccf的第一是实现一个计算器似乎要完成加减乘除,当时好像就过了样例点.现在回想起来实现其实就是语法树这一套
由于|();等调用会产生相当多复杂的命令和处理方式,实质上的处理时的各种递归调用其实就是一个语法树,这个树由5种基本命令构成

#define EXEC  1
#define REDIR 2
#define PIPE  3
#define LIST  4
#define BACK  5
struct cmd {
  int type;
};
struct execcmd {
  int type;
  char *argv[MAXARGS];
  char *eargv[MAXARGS];
};
struct redircmd {
  int type;
  struct cmd *cmd;
  char *file;
  char *efile;
  int mode;
  int fd;
};
struct pipecmd {
  int type;
  struct cmd *left;
  struct cmd *right;
};
struct listcmd {
  int type;
  struct cmd *left;
  struct cmd *right;
};
struct backcmd {
  int type;
  struct cmd *cmd;
};

以上代码在c语言中完成了继承和多态的性质,配合这两个性质,所有的

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值