MIT6.s081 lab utilities

lab utilities

1、sleep

//
// Created by silly on 23-9-5.
//
#include "../kernel/types.h"
#include "../kernel/stat.h"
#include "../user/user.h"

int main(int argc, char* argv[])
{
    if (argc != 2)
    {
        fprintf(2, "usage: sleep <number>\n");
        exit(1);
    }
    int number = atoi(argv[1]);
    sleep(number);
    exit(0);
}

2、pingpong

//
// Created by silly on 23-9-5.
//
#include "../kernel/types.h"
#include "../kernel/stat.h"
#include "../user/user.h"

int main() {
    int fd1[2], fd2[2];
    pipe(fd1);
    pipe(fd2);
    char buf[1] = {'p'};
    int pid = fork();
    if (pid == 0) {
        int child_pid = getpid();
        close(fd1[1]);
        close(fd2[0]);
        read(fd1[0], buf, 1);//read会阻塞在收到byte之前
        printf("%d: received ping\n", child_pid);
        write(fd2[1], buf, 1);
        exit(0);
    } else {
        int parent_pid = getpid();
        close(fd1[0]);
        close(fd2[1]);
        write(fd1[1], buf, 1);
        read(fd2[0], buf, 1);
        printf("%d: received pong\n", parent_pid);
        exit(0);
    }
}

一条pipe只能进行单向的数据传输,且在传输时应关闭掉无用的剩下两个端口

3.primes

As another example, which Hoare credits to Doug McIlroy, consider the generation of all primes less than a thousand. The sieve of Eratosthenes can be simulated by a pipeline of processes executing the following pseudocode:

p = get a number from left neighbor
print p
loop:
    n = get a number from left neighbor
    if (p does not divide n)
        send n to right neighbor

A generating process can feed the numbers 2, 3, 4, ..., 1000 into the left end of the pipeline: the first process in the line eliminates the multiples of 2, the second eliminates the multiples of 3, the third eliminates the multiples of 5, and so on:

img

//
// Created by silly on 23-9-5.
//
#include "../kernel/types.h"
#include "../kernel/stat.h"
#include "../user/user.h"

void primes(int readfd) {
    int now_num = 0;
    int my_num = 0;
    int fork_num = 0;
    int pipes[2];

    while (1) {
        int read_num = read(readfd, &now_num, 4);

        // 1.first receive left number
        if (!my_num) {
            my_num = now_num;
            printf("prime %d\n", my_num);
        }

        // 2.left number is prime
        if (now_num % my_num != 0) {
            if (!fork_num) {
                pipe(pipes);
                fork_num = 1;
                if (fork() == 0) {
                    close(pipes[1]);
                    primes(pipes[0]);
                    exit(0);
                }
                close(pipes[0]);
            }
            //为什么要写到if(!fork_num)外面
            //因为只要不是能整除my_num的数,都要往后传
            write(pipes[1], &now_num, 4);
        }

        // 3.left has not number
        if (read_num == 0) {
            close(readfd);
            if (fork_num) {
                close(pipes[1]);
                int child_status;
                wait(&child_status);
            }
            // 运行到此处说明是最后一个线程,它的fork_num = 0;
            exit(0);
        }
    }
}

int main() {
    int pipes[2];
    pipe(pipes);
    for (int n = 2; n <= 35; n++) {
        write(pipes[1], &n, 4);
    }
    close(pipes[1]);
    primes(pipes[0]);
    exit(0);
}

4.find

//
// Created by silly on 23-9-5.
//
#include "../kernel/types.h"
#include "kernel/fcntl.h"
#include "../kernel/stat.h"
#include "../user/user.h"
#include "../kernel/fs.h"

/*
 *	fmtname:将path(绝对路径)中最后的文件名获取出来
 *	eg:fmtname("./a/b") = "b";
 */
char* fmtname(char *path)
{
    char *p;

    // Find first character after last slash.
    for(p=path+strlen(path); p >= path && *p != '/'; p--)
        ;
    p++;

    return p;
}

void finds(char *path, char *target) {
    char buf[512], *p;
    int fd;
    struct dirent de;
    struct stat st;

    if((fd = open(path, O_RDONLY)) < 0){
        fprintf(2, "ls: cannot open %s\n", path);
        return;
    }
    if(fstat(fd, &st) < 0){
        fprintf(2, "ls: cannot stat %s\n", path);
        close(fd);
        return;
    }

    switch (st.type) {
        case T_FILE:
            if (strcmp(target, fmtname(path)) == 0) {
                printf("%s\n", path);
            }
            break;

        case T_DIR:
            memset(buf, 0, sizeof(buf));
            int path_len = strlen(path);
            memcpy(buf, path, path_len);
            buf[path_len] = '/';
            p = buf + path_len + 1;
            while (read(fd, &de, sizeof(de)) == sizeof(de)) {
                if (de.inum == 0 || strcmp(de.name, ".") == 0 ||
                    strcmp(de.name, "..") == 0)
                    continue;
                memcpy(p, de.name, DIRSIZ);
                p[DIRSIZ] = 0;
                finds(buf, target);
            }
            break;
    }
    close(fd);
}

int main(int argc, char *argv[]) {
    finds(argv[1], argv[2]);
    exit(0);
}

5、xargs

# $ echo hello too | xargs echo bye
管道 | 是xv6已经设置好的,我们通过main函数读取的argv列表内容只是{{echo}, {bye}},而{{hello}, {too}}参数是通过读取标准输入获得,因为管道的作用就是把echo hello too的输出通过管道发给了xargs
//
// Created by silly on 23-9-6.
//
#include "../kernel/types.h"
#include "../kernel/stat.h"
#include "../kernel/param.h"
#include "../user/user.h"


int main(int args, char *argv[]) {
    char buf[64] = {0};//通过buf到标准输入读取需要加上的额外参数
    char *new_argv[MAXARG] = {0};

    for (int i = 1; i < args; i++) {
        new_argv[i - 1] = argv[i];
    }

    while (1) {
        int i = 0;
        while (read(0, buf + i, 1) > 0) {
            if (buf[i] == '\n') break;
            i++;
        }
        if (i == 0) break;//read no data 
        buf[i] = 0;
        new_argv[args - 1] = buf;
        if (fork() == 0) {
            exec(new_argv[0], new_argv);
            exit(0);
        } else {
            wait(0);
        }
    }
    exit(0);
}

posted @   silly19  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示