xv6系列 util实验

Sleep

没啥难度,主要调用系统调用 sleep

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

int  
main(int argc, char *argv[])  
{
    char *err1 = "not right\0";
    char *err2 = "sleep wrong\0";

    if (argc != 2) {
        write(2, err1, strlen(err1));
    }
    int n = atoi(argv[1]);
    int ret = sleep(n);
    if (ret < 0) {
        write(2, err2, strlen(err2));
    }
    exit(0);
}

pingpong

熟悉一下fork以及pipe的用法,xv6 book介绍比较详细

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

int  
main(int argc, char *argv[])  
{
    char *err1 = "len(argc) not right\n0";
//    char *err2 = "pipe faile\0";
    char *err3 = "fork faile\0";

    char buf[8];

    if (argc != 1) {
        write(2, err1, strlen(err1));
        exit(1);
    }
    int p[2];
    pipe(p);

    int pid = fork();
    if (pid < 0) {
        write(2, err3, strlen(err3));
        exit(1);
    }
    if (pid == 0) {
        // child receive one byte
        if (read(p[0], buf, 1) == 1) {
            printf("%d: received pong\n", getpid());
        }
        // child send one byte
        write(p[1], "c", 1);
        exit(0);
    }

    // parent send one byte
    write(p[1], "p", 1);
    // parent receive one byte
    if (read(p[0], buf, 1) == 1) {
        printf("%d: received ping\n", getpid());
    }

    exit(0);
}

primes

看网上到处都是递归版本,实际只要找到循环节是啥即可

有两个注意的细节点 1. close要放在前面,只读不写的需要先把写close了,否则另一个子进程可能会卡死
2. wait需要加一下,否则输出容易串场

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

int  
main(int argc, char *argv[])  
{
    char *err1 = "fork failed\0";

    int prev[2];
    pipe(prev);

    int pid = fork();

    if (pid < 0) {
        write(2, err1,  strlen(err1));
        exit(1);
    }

    if (pid == 0) {
        while(1) {
            int base = 0;
            close(prev[1]);  // 有两个点需要注意,这个close要放在前面,只读不写的需要先把写close了;wait需要加一下,否则容易串场
            if(0 == read(prev[0], &base, sizeof(base))) {
                // printf("read == 0\n");
                close(prev[0]);
                exit(0);
            }
            // printf("read <- %d\n", base);
            printf("prime %d\n", base);

            int next[2];
            pipe(next);
            int pid = fork();
            if (pid < 0) {
                write(2, err1, strlen(err1));
                exit(1);
            }

            // parent
            if (pid > 0) {
                int cur = 0;
                for(;0 != read(prev[0], &cur, sizeof(cur));) {
                    if (0 != cur % base) {
                        write(next[1], &cur, sizeof(cur));
                    }
                }
                close(prev[0]);
                close(next[0]);
                close(next[1]);
                wait(0);
                exit(0);
            }

            // child
            close(prev[0]);
            prev[0] = next[0];
            prev[1] = next[1];
        }
        exit(0);
    }

    // parent
    close(prev[0]);
    for (int i = 2;i <= 32;i++) {
        // printf("write -> %d\n", i);
        write(prev[1], &i, sizeof(i));
    }
    close(prev[1]);
    wait(0);

    exit(0);
}

find

  1. pfilename是稍微改了ls.c的fmtfilename
  2. c语言中的字符串最后末尾不上 0
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fs.h"

char*  
pfilename(char *path)  
{
  char *p;

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

  return p;
}



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

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

    switch(st.type) {
        case T_FILE:
            if(0 == strcmp(pfilename(path), filename)) {
                fprintf(1, "%s\n", path);
            }
            break;
        case T_DIR:
            strcpy(buf, path);
            p = buf + strlen(buf);
            *p++='/';
            while(read(fd, &de, sizeof(de)) == sizeof(de)) {
                if(de.inum == 0) {
                    continue;
                }
                if(0 == strcmp(".", de.name) || 0 == strcmp("..", de.name)) {
                    continue;
                }
                memmove(p, de.name, DIRSIZ);
                p[DIRSIZ] = 0;
                if(stat(buf, &st) < 0) {
                    printf("find: cannot stat %s\n", buf);
                    continue;
                }

                find(buf, filename);
            }
            break;
    }
    close(fd);
    return 0;
}

int  
main(int argc, char *argv[])  
{
    if (argc < 3) {
        fprintf(2, "not enough arguments\n");
        exit(1);
    }
    find(argv[1], argv[2]);
    exit(0);
}