6.s081 lab1.3--primes【小白思路理清向】

MIT 6.s081 lab1.3–primes

No.1 写在前面的话

这是我目前为止觉得最难的实验【比xargs和find要难】,在看完提示后也丝毫没有进展,因为想要自己做不依靠他人文章,费了不少时间。不过,在理清思路后写起来就容易得多【虽然中间实现素数筛读取那里不会,参考了他人】,但是基本的框架已经形成。那么,开始吧!

No.2 预备知识

为了搞懂素数筛以及如何创建多个管道,下面的链接是必要参考的:

埃拉托色尼筛:primes【里面的代码必须亲自调试理解】

进程拷贝:[创建多个进程](fork 循环创建多个子进程_fork多个子进程-CSDN博客)【进一步理解管道】

通过理解素数筛的机制,大概知道,它通过数组置一,如果为倍数则置零排除的方法取得结果;而如果要利用fork,父进程写入数字,由子进程进行连续筛选,那么就得是嵌套结构。自然,main函数如果在fork中又fork,筛选进程就得套很多fork,这必然不现实。那么就利用了递归思想。

初步的思路如下:【实际上,在我参看文章时,发现自己的思路已经基本正确了】

Imgur

画图示意;

Imgur

No.3 primes的实现

有了上述的思路,实现就好写多了,根据实验提示,代码如下:

来自[爱你哦小猪猪](操作系统MIT6.S081:Lab1->Unix utilities_mit6s081详解_爱你哦小猪猪的博客-CSDN博客),我的代码和他写的基本一致,但是不知为何总是prime 0?,所以在这里为了避免大家出错,贴上正确的代码。如果有大佬知道怎么解决,请评论我,谢谢(_)

#include "kernel/types.h"
#include "user/user.h"
#define N 35

void solve(int* pl){
    int prime;
    //读取一个质数,如果没有数据了则直接返回
    if(read(pl[0], &prime, sizeof(prime)) == 0) return;
    printf("prime %d\n", prime); //打印输出
    int pr[2];
    pipe(pr);  //right管道

    int pid = fork();
    if(pid > 0){ //父进程
        close(pr[0]); //关闭right管道读取端
        //将当前质数的倍数筛出去,剩下的写入right管道写入端
        for(int t; read(pl[0], &t, sizeof(t)) != 0;){
            if(t % prime != 0)
                write(pr[1], &t, sizeof(t));
        }
        close(pr[1]); //关闭right管道写入端
        close(pl[0]); //关闭left管道读取端
        wait(0); //等待子进程完成
        exit(0); //正确退出

    }else if(pid == 0){
        close(pr[1]); //关闭right管道写入端
        close(pl[0]); //关闭left管道写入端
        solve(pr); //递归处理右邻
        close(pr[0]); //关闭right管道读取端
        exit(0); //正确退出
    }
    else{ //创建进程失败
        close(pl[0]);
        close(pr[1]);
        close(pr[0]);
        exit(1); //错误退出
    }
}

int main(int argc, char argv[]){
    int pl[2];  //lefts
    pipe(pl);  //创建left管道
    int pid = fork();
    if(pid > 0){ //主进程
        close(pl[0]);  //关闭left管道读取端
        for(int i =2 ; i <= N; ++i){ //将2-35写入left管道写入端
            write(pl[1], &i, sizeof(i));
        }
        close(pl[1]); //关闭left管道写入端
        wait(0);  //等待子进程完成
        exit(0);  //成功退出
    }else if(pid == 0){ //子进程
        close(pl[1]);  //关闭left管道写入端
        solve(pl);  //进行筛选
        close(pl[0]); //关闭left管道读取端
        exit(0); //正确退出
    }else{  //创建进程错误
        close(pl[1]);  
        close(pl[0]);
        exit(1);
    }
}

接下来这个是传入数组的代码,我不太理解为什么中途没有关闭管道,但运行后结果也是对的,贴上链接供大家参考:MIT操作系统实验lab1(案例:primes(质数筛选)附代码、详解)

虽然自己的代码因为未知原因通不过,但看完他人的文章知道自己的代码写的是基本正确的,也满足了,了解思想很重要。【用时两天】

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值