xv6-2023 - primes Lab

xv6-2023 - primes Lab

Overview

Write a user-level program that uses xv6 system calls to find prime numbers using a pipeline of processes. The program should generate numbers from 2 to 35, and use a recursive pipeline approach where each process in the pipeline filters out multiples of a prime number it receives. Each process should print the prime number it finds and pass the remaining numbers to the next process. Your solution should be in the file user/primes.c.

Some hints:

  • Add the program to UPROGS in Makefile.
  • Use pipe to create pipes for inter-process communication.
  • Use fork to create child processes.
  • Use read to read from a pipe, and write to write to a pipe.
  • Use recursion to create a pipeline of processes.
  • User programs on xv6 have a limited set of library functions available to them. You can see the list in user/user.h; the source (other than for system calls) is in user/ulib.c, user/printf.c, and user/umalloc.c.

solve it

根据上文的信息,我们知道我们要使用pipe()fork()函数,以及递归来实现一个质数筛选器。程序应该生成数字2到35,然后通过管道传递给第一个进程。每个进程从管道中读取第一个数字作为质数,然后过滤掉所有能被这个质数整除的数字,将剩余的数字传递给下一个进程。

我们通过阅读代码可以了解到,这个程序使用了递归的方式来创建进程管道。每个进程负责:

  1. 从父进程的管道中读取第一个数字作为质数
  2. 打印这个质数
  3. 创建一个新的管道
  4. 创建一个子进程来处理剩余的数字
  5. 过滤掉所有能被当前质数整除的数字,将剩余的数字写入子进程的管道

pipe 和 fork

我们先来看pipe()fork()的使用:

pipe(int p[2]) 创建一个管道,其中 p[0] 是读端,p[1] 是写端。

fork() 创建一个子进程,在父进程中返回子进程的PID,在子进程中返回0。

递归过程

程序的核心是primes()函数的递归调用:

c 复制代码
void primes(int p0) {
    int prime;
    if (read(p0, &prime, sizeof(prime)) <= 0) {
        close(p0);
        exit(0);
    }
    printf("prime %d\n", prime);

    int p[2];
    pipe(p);

    if (fork() == 0) {
        // 子进程
        close(p[1]);   // 只读
        primes(p[0]);  // 递归
    } else {
        // 父进程
        close(p[0]);   // 只写
        int n;
        while (read(p0, &n, sizeof(n)) > 0) {
            if (n % prime != 0) {
                write(p[1], &n, sizeof(n));
            }
        }
        close(p[1]);
        close(p0);
        wait(0);
        exit(0);
    }
}

main 函数

main()函数负责初始化过程:

c 复制代码
int main() {
    int p[2];
    pipe(p);

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

工作流程

  1. main()函数创建第一个管道并生成数字2-35
  2. 第一个子进程调用primes()开始递归过程
  3. 每个primes()调用:
    • 读取第一个数字作为质数并打印
    • 创建新的管道和子进程
    • 过滤掉当前质数的倍数,将剩余数字传递给子进程
  4. 当没有更多数字可读时,递归终止

code

c 复制代码
#include "kernel/types.h"
#include "user/user.h"

void primes(int p0) {
    int prime;
    if (read(p0, &prime, sizeof(prime)) <= 0) {
        close(p0);
        exit(0);
    }
    printf("prime %d\n", prime);

    int p[2];
    pipe(p);

    if (fork() == 0) {
        // 子进程
        close(p[1]);   // 只读
        primes(p[0]);  // 递归
    } else {
        // 父进程
        close(p[0]);   // 只写
        int n;
        while (read(p0, &n, sizeof(n)) > 0) {
            if (n % prime != 0) {
                write(p[1], &n, sizeof(n));
            }
        }
        close(p[1]);
        close(p0);
        wait(0);
        exit(0);
    }
}

int main() {
    int p[2];
    pipe(p);

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

运行成功的输出为:

bash 复制代码
prime 2
prime 3
prime 5
prime 7
prime 11
prime 13
prime 17
prime 19
prime 23
prime 29
prime 31
相关推荐
树℡独3 小时前
ns-3仿真之应用层(五)
服务器·网络·tcp/ip·ns3
小小管写大大码3 小时前
如何让vscode变得更智能?vscode接入claude实现自动编程
运维·ide·vscode·自动化·编辑器·ai编程·腾讯云ai代码助手
嵩山小老虎3 小时前
Windows 10/11 安装 WSL2 并配置 VSCode 开发环境(C 语言 / Linux API 适用)
linux·windows·vscode
Fleshy数模4 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
zhang133830890754 小时前
CG-09H 超声波风速风向传感器 加热型 ABS材质 重量轻 没有机械部件
大数据·运维·网络·人工智能·自动化
a41324474 小时前
ubuntu 25 安装vllm
linux·服务器·ubuntu·vllm
Configure-Handler4 小时前
buildroot System configuration
java·服务器·数据库
津津有味道4 小时前
易语言TCP服务端接收刷卡数据并向客户端读卡器发送指令
服务器·网络协议·tcp·易语言
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.5 小时前
Keepalived VIP迁移邮件告警配置指南
运维·服务器·笔记
物联网软硬件开发-轨物科技5 小时前
【轨物洞见】告别“被动维修”!预测性运维如何重塑老旧电站的资产价值?
运维·人工智能