6.S081 Lab util: Unix utilities

primes (moderate)/(hard)

Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, inventor of Unix pipes. The picture halfway down this page and the surrounding text explain how to do it. Your solution should be in the file user/primes.c.

Your goal is to use pipe and fork to set up the pipeline. The first process feeds the numbers 2 through 35 into the pipeline. For each prime number, you will arrange to create one process that reads from its left neighbor over a pipe and writes to its right neighbor over another pipe. Since xv6 has limited number of file descriptors and processes, the first process can stop at 35.

Some hints:

  • Be careful to close file descriptors that a process doesn't need, because otherwise your program will run xv6 out of resources before the first process reaches 35.
  • Once the first process reaches 35, it should wait until the entire pipeline terminates, including all children, grandchildren, &c. Thus the main primes process should only exit after all the output has been printed, and after all the other primes processes have exited.
  • Hint: read returns zero when the write-side of a pipe is closed.
  • It's simplest to directly write 32-bit (4-byte) ints to the pipes, rather than using formatted ASCII I/O.
  • You should create the processes in the pipeline only as they are needed.
  • Add the program to UPROGS in Makefile.

Your solution is correct if it implements a pipe-based sieve and produces the following output:

    $ make qemu
    ...
    init: starting sh
    $ primes
    prime 2
    prime 3
    prime 5
    prime 7
    prime 11
    prime 13
    prime 17
    prime 19
    prime 23
    prime 29
    prime 31
    $
  

本题耗费了我近三个小时才解决,关键的几个点:

  1. 使用数组作为buffer来传递数据;
  2. 在管道写入完成之后将其关闭,这样read()端会返回0,终止循环;
  3. 判断read()的返回码,避免无效创建;
  4. wait(0); 等待所有子进程结束。

 

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


void primes(int p[2]){
  close(p[1]);
  int right[1];
  int first[1];
  if(!read(p[0],first,4)){
      return ;
  }
  printf("prime %d\n",first[0]);
  int p2[2];
  pipe(p2);
  if(fork() == 0){
      primes(p2);
  }else{
        while(read(p[0],right,4)){
            if( right[0] % first[0] != 0){
                write(p2[1],right,4);
            }
        }
        close(p2[1]);
  }
}

int main(int argc, char *argv[])
{

  int p[2];
  int left[1];

  pipe(p);
  if(fork()==0){
      primes(p);
   }else{
  for (int i = 2; i <= 35; i++)
    {
      left[0] = i;
      write(p[1],left,4);
  }
  close(p[1]);
  
 }
 wait(0);
  exit(0);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值