6.S081-实验1-Xv6 and Unix utilities

实现sleep

输入数字,使系统睡眠ms

代码实现

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

int main(int argc, char *argv[]){
    if(argc < 2){
        fprintf(2, "argument 1 must sleep\n");
        exit(1);
    }

    for(int i = 1; i < argc; i++){
        int t = atoi(argv[i]);
        printf("sleeping\n");
        sleep(t);
        printf("not sleep\n");
    }
    exit(0);
}

实现pingpong

写一个程序,实现字符串在两个进程间来回传递1次

实现思路

在这里插入图片描述

代码实现

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

int main(){
    // p1  写端父进程,读端子进程
    // p2  写段子进程,读端父进程
    int p1[2], p2[2];
    
    // 传输的字符
    char buf[] = {"zhaoxinhao\n"};

    // 传输字符的长度
    int len_buf = sizeof(buf);

    // 创建管道
    pipe(p1);
    pipe(p2);

    // 创建子进程
    int pid = fork();
    if(pid < 0){
        printf("fork error");
        exit(1);
    }
    else if(pid == 0){  // 子进程
        // p1的读端   p2的写端
        // 关闭 p1的写端  p2的读端
        close(p1[1]);
        close(p2[0]);
        printf("This is child\n");
        int child_read_n = read(p1[0], buf, len_buf);
        if(child_read_n == 0){
            printf("child read error");
            exit(1);
        }
        
        write(1, buf, len_buf); // 向标准输出  打印读到的数据
        printf("%d: received ping\n", getpid());
        if((write(p2[1], buf, len_buf)) != len_buf){
            printf("child write error");
            exit(1);
        }
        exit(0);
    }
    else{   // 父进程
        // p2的读端   p1的写端
        // 关闭 p2的写端  p1的读端
        close(p1[0]);
        close(p2[1]);
        printf("This is parent\n");
        if(write(p1[1], buf, len_buf) != len_buf){
            printf("parent write error");
            exit(1);
        }

        if(read(p2[0], buf, len_buf) == 0){
            printf("parent read error");
            exit(1);
        }
        
        write(1, buf, len_buf);
		printf("%d: received pong\n", getpid());


        exit(0);
    }
}o

实现primes(素数)

打印2~35之间的素数,利用管道

实现思路

  1. 找素数:对每个素数,乘以k倍所得到的数都不是素数——哈希去掉不是素数的数
  2. 管道实现:
    1. 主进程将素数写入,子进程读出
    2. 子进程递归继续找下一个素数
    3. 重复1和2
    4. writeread使用的都是地址,传入4个字节的地址,正好int

代码实现

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

void func(int *input, int cnt){
    if(cnt >= 36) return;
    int p[2];
    pipe(p);
    int i = cnt;
    for(; i < 36; i++){
        if(input[i] == 1) continue;
        int k = 1;
        while(k * i < 36 ){
            input[k++ * i] = 1;
        }
        break;
    }
    if(i >= 36) return;
    int pid = fork();
    if(pid < 0){
        printf("fork error\n");
        exit(1);
    }
    else if(pid == 0){
        int buf;
        close(p[1]);    // 关闭写端
        // close(0);
        // dup(p[0]);
        if(read(p[0], &buf, 4) <= 0){
            printf("read error\n");
            exit(1);  
        }
        printf("primes: %d\n", buf);

        close(p[0]);
 
        func(input, i);
        exit(0);
    }
    else{
        close(p[0]);
        if(write(p[1], &i, 4) <= 0){
            printf("write error\n");
            exit(1); 
        }
        close(p[1]);
        wait(0);
        exit(0);
    }
}

int main(){
    int p[36] = {0};
    func(p, 2);
    exit(0);
}

实现find

实现find功能,查找当前目录下,所有的复合名字的文件名

实现思路

  1. 参考ls
  2. 利用kernel/stat.h下的stat结构体,获取当前目录下所有文件和文件夹的类型
  3. 利用kernel/fs.h下的dirent结构体,获取当前文件或文件夹的名字和inode
  4. 利用递归遍历文件夹下的所有文件

代码实现

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

char* fmt_name(char *path){
    static char buf[DIRSIZ+1];
    char *p;
    // Find first character after last slash.
  for(p = path + strlen(path); p >= path && *p != '/'; p--)
    ;
  p++;

  memmove(buf, p, strlen(p)+1);
  return buf;
}

void campare(char *fileName, char *findName){
    char *file_name = fmt_name(fileName);
    // printf("%s\n", file_name);
	if(strcmp(file_name, findName) == 0){
		printf("find: %s\n", fileName);
	}
}

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

    if((fd = open(path, 0)) < 0){
        printf("open %s failure\n", path);
        return;
    }
    // st:传出参数,获取文件描述符的状态
    if(fstat(fd, &st) < 0){ 
        printf("stat %s failure\n", path);
    }

    switch (st.type)
    {
    case T_FILE:
        campare(path, file_name);
        break;
    case T_DIR:
        if(strlen(path) + 1 + DIRSIZ + 1 > sizeof(buf)){
            printf("path too long");
            break;
        }
        strcpy(buf, path);
        p = buf + strlen(buf);
        *p++ = '/';
        // 读取当前目录下所有文件和文件夹
        while(read(fd, &de, sizeof(de)) == sizeof(de)){
            // printf("de.name:%s, de.inum:%d\n", de.name, de.inum);
            if(de.inum == 0 || de.inum == 1 || strcmp(de.name, ".") == 0 ||
                strcmp(de.name, "..") == 0)
                continue;
            memmove(p, de.name, strlen(de.name));
            p[strlen(de.name)] = 0;
            find(buf, file_name);
        }
        break;
    default:
        break;
    }
    close(fd);
}

int main(int argc, char *argv[]){
    if(argc < 3){
        printf("find errorL: find [path] [fileName]");
        exit(1);
    }

    find(argv[1], argv[2]); 
    exit(0);    
}

实现xargs

类似于:echo hello too | xargs echo bye => bye hello too

代码实现

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

int main(int argc, char* argv[])
{
    char buf[32];
    int n;
    // 没有参数读到什么输出什么(没有必要)
    if (argc < 2) {
        while((n = read(0, buf, sizeof buf)) > 0) {
            write(1, buf, n);
        }
        exit(0);
    }
    char* args[32];
    int numArg;
    for (int i = 1; i < argc; ++i) {
        args[i-1] = argv[i];
    }
    numArg = argc - 1;
    char* p = buf;
    // 读取管道xargs 之前的命令
    while ((n = read(0, p, 1)) > 0) {
        if (*p == '\n') {
            *p = 0;
            if (fork() == 0) {
                args[numArg] = buf;
                exec(args[0], args);
                exit(0);
            } else {
                wait(0);
            }
            p = buf;
        } else {
            ++p;
        }
    }
    exit(0);
}

= ‘\n’) {
*p = 0;
if (fork() == 0) {
args[numArg] = buf;
exec(args[0], args);
exit(0);
} else {
wait(0);
}
p = buf;
} else {
++p;
}
}
exit(0);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: xv6是一个基于Unix的操作系统,它是由麻省理工学院开发的一个教学用途的操作系统。它的设计和实现都非常简单,因此非常适合用于操作系统的教学和学习。Unix utilitiesUnix操作系统中的一些常用工具,例如ls、grep、awk、sed等,它们可以帮助用户完成各种任务,例如查看文件、搜索文本、处理数据等。这些工具也被移植到了其他操作系统中,成为了广泛使用的工具。 ### 回答2: xv6是一个教学目的的操作系统内核,它是根据Unix第六版(Version 6 Unix)设计而成的。Unix utilities是指Unix操作系统中提供的一系列实用工具程序。 xv6的设计灵感来自于Unix,因此它具有类似于Unix的文件系统、进程管理、内存管理等特性。它采用C语言编写,具有简洁的结构和易于理解的代码,这使得学生可以更好地理解操作系统的内部工作原理。xv6内核为学生提供了一个可用于学习和实验的平台,帮助他们深入了解操作系统和计算机系统的工作方式。 与此同时,Unix utilities是一些用于完成特定任务的Unix命令行工具程序。这些工具程序通常被用于处理文件、管理进程、网络通信、文本处理等方面。常见的Unix utilities包括ls(列出目录内容)、grep(查找指定模式)、cp(复制文件)、rm(删除文件)等等。这些工具程序非常强大且灵活,可以通过简单的命令行参数来满足各种不同需求。 xv6Unix utilities有着密切的关系。学习和理解xv6可以帮助我们深入理解Unix操作系统的设计和实现原理。而掌握Unix utilities可以使我们更加高效地处理各种系统管理任务和编程工作。通过学习和使用这些工具,我们可以更好地理解和应用操作系统的概念和原则,提高我们的计算机系统操作和编程技能。总之,xv6Unix utilities都为我们提供了学习和实践操作系统的机会,帮助我们更好地掌握计算机系统的核心知识。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值