Lab1: Xv6 and Unix utilities

配置问题:

  1. /usr/bin/env: ‘python’: No such file or directory

解决:/usr/bin/env: ‘python’: No such file or directory

lab

sleep:

作为新手我的第一个想法居然是:int sleep(int ),以为这个题目是要编写一个函数调用。没有理解shell中的一个个指令背后是什么。

image

看到这张图片有些领悟,操作系统的内核态提供了一些接口供用户态运行的程序使用,我要做的应该是编写一个运行在用户态的程序,他能使用内核态的接口实现目标功能。

而这个运行在用户态的程序并不是shell的接口函数,他也是一个程序,shell也是一个程序,shell通过fork和exec来运行这个程序。

shell 是一个普通的程序,它接受用户输入的命令并且执行它们,它也是传统 Unix 系统中最基本的用户界面。shell 作为一个普通程序,而不是内核的一部分,充分说明了系统调用接口的强大:shell 并不是一个特别的用户程序。

进程通过系统调用使用内核服务。系统调用会进入内核,让内核执行服务然后返回。所以进程总是在用户空间和内核空间之间交替运行。

#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 ticks...");
        exit(1);
    }
    
    sleep(atoi(argv[1]));

    exit(0);
}

pingpong:

主要注意管道的半双工特性,数据只能在一个方向上流动。

Linux下进程间通信方式——pipe(管道)

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

int main(int argc, char *argv[]) {
    char buf[10];
    int pid;
    int p1[2], p2[2];
    pipe(p1);
    pipe(p2);
    pid = fork();
    if (pid == 0) {
        close(p1[1]); // p1 子读父写
        close(p2[0]); // p2 子写父读
        int ret = read(p1[0], buf, sizeof(buf));
        if (ret > 0) {
            printf("%d: received ping\n", getpid());
            write(p2[1], "pong", 5);
        } else {
            printf("close or error\n");
        }
        exit(0);
    } else if (pid > 0) {
        close(p1[0]);
        close(p2[1]);
        write(p1[1], "ping", 5);
        int ret = read(p2[0], buf, sizeof(buf));
        if (ret > 0) {
            printf("%d: received pong\n", getpid());
        } else {
            printf("close or error\n");
        }
    } else {
        printf("fork error\n");
    }
    exit(0);
}

primes:(难顶)

参考:Bell Labs and CSP Threads
image

Hint: read returns zero when the write-side of a pipe is closed.

find:(难顶)

还是没有理解递归的思路,实际上就是在文件对比时出现答案,在目录时继续递归,大部分代码和参考的ls.c一模一样。唉。

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

char* fmtname(char *path) {
    char *prev = 0, *cur = strchr(path, '/');
    while (cur != 0) {
        prev = cur;
        cur = strchr(cur+1, '/');
    }
    return prev;
} 

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

    if ((fd = open(path, 0)) < 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: {
            char *f_name = fmtname(path);
            int isOK = 1;
            if (f_name == 0 || strcmp(f_name+1, filename) != 0) {
                isOK = 0;
            }
            if (isOK) {
                printf("%s\n", path);
            } else {
                printf("error: mismatching\n");
            }
            close(fd);
            break;
        }
        case T_DIR: {
            if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){
                printf("find: path too long\n");
                break;
            }
            memset(buf, 0, sizeof(buf));
            uint 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;
                }
                printf("test:%s\n", de.name);
                memmove(p, de.name, DIRSIZ);
                p[DIRSIZ] = 0;
                find(buf, filename);
            }
            close(fd);
            break;
        }
    }
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Usage: find [DIR] [filename]\n");
        exit(1);
    }
    find(argv[1], argv[2]);
    exit(0);
}

xargs:

xargs 命令教程

xargs命令的作用,是将标准输入转为命令行参数。

posted @ 2023-10-31 15:49  HDD-SG  阅读(52)  评论(0)    收藏  举报