《6.S081: Operating System Engineering》Lab util: Unix utilities

2 篇文章 0 订阅

之前学习6.828没坚持下去,最近突然发现2020fall的更新了,并且还有学习视频了,参考资料貌似更详细了作业也变得十分友好。又重新燃起了学习的兴趣。于是开始重新启动6.S081的学习。
课程Schedule课程相关资料基本都在这个网站上了。
我的github

环境搭建

我在本地搞了试了16.04、18.04和20.04的虚拟机都没法成功的按照lab tools page配置环境,很奇怪。正好手头有一个阿里云的ubuntu20.04的服务器(做到后面发现这个1核2G的根本没法完成后面的实验,测试样例各种超时,听说后面还有测试样例必须是多核才能运行的,推荐还是在本地安装ubuntu20.04的虚拟机,更新一下apt源就可以了),按照上述网站指示,配置成功了。本次lab没写后面的challenge,单纯写代码大概耗时3-4小时吧?如果加上阅读文档可能有7-8小时。

sleep

熟悉一下system call,没啥好说的。

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

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(2, "usage: sleep n ticks...\n");
        exit(1);
    }
    //sleep n ticks
    int n = atoi(argv[1]);
    if (sleep(n) != 0) {
        fprintf(2, "sleep: sleep system call error\n");
        exit(1);
    }
    fprintf(1, "(nothing happens for a little while)\n");
    exit(0);
}

pingpong

熟悉一下system call,没啥好说的。

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

int main(int argc, char **argv) {
    char buf[1];
    int p1[2]; //parent -> child
    int p2[2]; //child -> parent
    int pid;
    pipe(p1);
    pipe(p2);
    int n;

    if ((pid = fork()) < 0) {
        fprintf(2, "fork: fork system call error\n");
        exit(1);
    }

    if (pid == 0) {  //child
        pid = getpid();
        if((n = read(p1[0], buf, 1)) < 0) {
            fprintf(2, "read: read system call error\n");
            exit(1);
        }
        fprintf(1, "%d: received ping\n", pid);
        if((n = write(p2[1], buf, 1)) < 0) {
            fprintf(2, "write: write system call error\n");
            exit(1);
        }
    } else {    //parent
        pid = getpid();
        if((n = write(p1[1], buf, 1)) < 0) {
            fprintf(2, "write: write system call error\n");
            exit(1);
        }
        if((n = read(p2[0], buf, 1)) < 0) {
            fprintf(2, "read: read system call error\n");
            exit(1);
        }
        fprintf(1, "%d: received pong\n", pid);
    }
    exit(0);
}

primes

递归,没什么好说的,我用了点小trick,当递归到num>11(即只打印11个数字)时候是递归边界。没想到啥好的解决方案。晕。

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

void primes(int left_pipe_in, int num) {
    if (num > 11)
        exit(0);
    int right_pipe[2];
    int pid;
    pipe(right_pipe);
    
    if ((pid = fork()) == 0) { // child
        close(right_pipe[1]);
        primes(right_pipe[0], num + 1);
    } else {    //parent
        close(right_pipe[0]);
        int p, n;
        read(left_pipe_in, &p, sizeof(p));
        printf("prime %d\n", p);
        //read returns zero when the write-side of a pipe is closed.
        for (int i = 1; read(left_pipe_in, &n, sizeof(n)) != 0; i++) {
            if (n % p != 0)
                write(right_pipe[1], &n, sizeof(n));
        }
        close(right_pipe[1]);
        wait(0);
    }
}

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

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

find

看看ls.c的代码,总结一下对于文件系统,通过open打开文件,创建fd,通过fstat(fd,...)获取文件的属性,如果是文件夹,则通过read(fd,...)去读取子文件到struct dirent中。

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

int Open(const char* path, int x) {
    int fd;
    if ((fd = open(path, x)) < 0) {
        fprintf(2, "find: cannot open %s\n", path);
        exit(1);
    }
    return fd;
}

void Fstat(int fd, struct stat* st) {
    if (fstat(fd, st) < 0) {
        fprintf(2, "find: cannot stat fd\n", fd);
        close(fd);
        exit(1);
    }
}

void find(char *path, char *pattern) {
    char buf[512];
    char *p;
    int fd;
    struct dirent de;
    struct stat st;
    fd = Open(path, 0);
    Fstat(fd, &st);
    if (st.type != T_DIR)
        fprintf(2, "find: %s is not a directory\n", path);
    // printf("wq...debug\n");
    strcpy(buf, path);
    p = (buf + strlen(buf));
    *(p++) = '/';
    while (read(fd, &de, sizeof(de)) == sizeof(de)) {
        if (de.inum == 0 || strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) continue;
        // printf("de.inum:%d, de.name:%s\n", de.inum, de.name);
        // printf("wq...debug_begin\n");
        memmove(p, de.name, DIRSIZ);
        p[DIRSIZ] = 0;
        int tfd = Open(buf, 0);
        Fstat(tfd, &st);
        // printf("buf:%s, de.name:%s, st.type:%d\n", buf, de.name, st.type);
        if (st.type == T_DIR) {
            find(buf, pattern);
        } else if (strcmp(pattern, de.name) == 0) {
            printf("%s\n", buf);
        }
        // printf("wq...debug_end\n");
        close(tfd);
    }
    close(fd);
}

int main(int argc, char **argv) {
    if (argc < 3) {
        fprintf(2, "find: find dir files...\n");
        exit(1);
    }
    char* path = argv[1];
    char* pattern = argv[2];
    find(path, pattern);
    exit(0);
    //printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size);
}

xargs

这一题写的时候挺迷惑的,写到最后跑样例出错才发现理解错题目意思了,需要实现的xargs是类似xargs -n 1功能的,不是去匹配-n选项参数。

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

int main(int argc, char** argv) {
    char buf[256];
    char *new_argvs[MAXARG];
    char *p;
    if (argc < 2) {
        fprintf(2, "xargs: xargs [-n x] argv...\n");
        exit(1);
    }
    read(0, buf, 256);//strchr
    p = buf;

    for (int i = 1; i < argc; i++) {
        new_argvs[i - 1] = argv[i];
        //printf("argc = %d, argvs[%d] = %s\n", argc, i - 3, new_argvs[i - 3]);
    }
    while (1) {
        new_argvs[argc - 1] = p;
        new_argvs[argc] = 0;
        p = strchr(p, '\n');
        if (p == 0) break;
        *(p++) = 0;
        if (fork() == 0) {  //child
            exec(new_argvs[0], new_argvs);
        } else {
            wait(0);
        }
    }
    exit(0);
}

结果

在这里插入图片描述

Chanllenge

挑战的东西还是值得做一做的只是有点磨时间,后面我有空了再补补吧。

总结

进一步需要完成chanllenge,并且应该尽可能地读读kernel/user/里的代码,毕竟都是宝藏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值