Lab1 Xv6 and Unix utilities

实现几个unix实用工具,熟悉xv6的开发环境以及系统调用
实验环境搭建:使用Ubuntu20.04

  1. Sleep (easy)
    参考user/echo.c,添加头文件
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

参考user/ulib.c,把命令行参数string类型转换为int,使用atoi
在Makefile里把sleep加入构建目标里

UPROGS=\
    $U/_cat\
    $U/_echo\
    $U/_forktest\
    $U/_grep\
    $U/_init\
    $U/_kill\
    $U/_ln\
    $U/_ls\
    $U/_mkdir\
    $U/_rm\
    $U/_sh\
    $U/_stressfs\
    $U/_usertests\
    $U/_grind\
    $U/_wc\
    $U/_zombie\
    $U/_sleep\ 

代码:

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

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

测试
注意:评测脚本是python程序
第一行修改为:

!/usr/bin/ python

测试命令修改为:
python3 grade-lab-util sleep

捕获.PNG
  1. pingpong(easy)
    管道是一个小的内核缓冲区,它以文件描述符对的形式提供给进程,一个用于写操作,一个用于读操作。按照惯例,进程从文件描述符0读入(标准输入),从文件描述符1输出(标准输出)。
    方式一:创建2个管道,分别用于父子进程之间两个方向的数据传输
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int 
main(int argc, char *argv[])
{
    int p2c[2], c2p[2];
    pipe(p2c);
    pipe(c2p);

    if (fork() != 0) {
        write(p2c[1], "f", 1);
        char buf;
        read(c2p[0], &buf, 1);
        printf("%d: received pong\n", getpid());
        wait(0);
    } else {
        char buf;
        read(p2c[0], &buf, 1);
        printf("%d: received ping\n", getpid());
        write(c2p[1], &buf, 1);
    }

    exit(0);
}

测试结果:


pingpong2.PNG
pingpong1.PNG

方式二:创建1个管道
父子进程复用管道

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

int 
main(int argc, char *argv[])
{
    int p[2];
    pipe(p);

    if (fork() == 0) {
        char buf;
        read(p[0], &buf, 1);
        close(p[0]);

        printf("%d: received ping\n", getpid());
        write(p[1], "c", 1);

        close(p[1]);
        exit(0);
    } else {
        char buf;
        write(p[1], "f", 1);
        close(p[1]);

        wait(0);

        read(p[0], &buf, 1);
        close(p[0]);
        printf("%d: received pong\n", getpid());
        exit(0);
    }
}

测试结果:


pingpong4.PNG
pingpong3.PNG

primes (hard)
使用多进程和管道,每个进程作为一个节点,筛掉某个素数的所有倍数
注意:关闭不用的管道。

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

void primes(int p[2])
{   
    // 子进程只需要读,关闭写
    close(p[1]);
    int num;
    read(p[0], &num, sizeof(num)); //读取第一个数
    if (num == -1) {
        exit(0);
    }
    printf("prime %d\n", num);

    int p2[2];
    pipe(p2); // 创建用于下一阶段的管道

    if (fork() == 0) {
        close(p[0]); // 关闭读
        primes(p2);
    } else {
        close(p2[0]); // 主进程关闭读
        int num2;
        while (read(p[0], &num2, sizeof(num)) && num2 != -1) {
            if (num2 % num != 0) {
                write(p2[1], &num2, sizeof(num2));
            }
            
        }
        num2 = -1;
        write(p2[1], &num2, sizeof(num2));
        wait(0);
        exit(0);
    }
}

int
main(int argc, char *argv[]) 
{
    int p[2];
    pipe(p);

    if (fork() == 0) {
        primes(p);
        exit(0);
    } else {
        // 主进程只需要写,不需要读
        close(p[0]);
        int i;
        for (i = 2; i <= 35; i++) { // 管道里写入2-35
            write(p[1], &i, sizeof(i));
        }
        i = -1;
        write(p[1], &i, sizeof(i));
        close(p[1]); // 关闭写
        wait(0);
    }

    exit(0);
}

测试结果:


primes1.PNG
primes2.PNG
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容